810 likes | 1.07k Views
Multithread API’s. Adam Piotrowski Grzegorz Jabłoński. Lecture IV. Synchronisation. Mutexes Semaphores Condition Variables. Mutex.
E N D
Multithread API’s Adam Piotrowski Grzegorz Jabłoński Lecture IV
Synchronisation Mutexes Semaphores Condition Variables
Mutex The mutual exclusion lock is the simplest and mostprimitive synchronizationvariable. It provides a single, absolute owner for the section of code (thus acritical section) that it brackets between the calls to pthread_mutex_lock() and pthread_mutex_unlock(). The first thread that locks the mutex getsownership, and any subsequent attempts to lock it will fail, causing the callingthread to go to sleep.
Mutex initialisation NAME pthread_mutex_init, pthread_mutex_destroy- initializes mutex with attr or destroys the mutex, making it unusable in any form SYNOPSIS #include <pthread.h> int pthread_mutex_init(pthread_mutex_t *mutex, constpthread_mutexattr_t *attr); int pthread_mutex_destroy(pthread_mutex_t *mutex);
Mutex unlock operation NAME pthread_mutex_unlock- unlocks mutex and wakes up the first thread sleeping on it. SYNOPSIS #include <pthread.h> int pthread_mutex_unlock(pthread_mutex_t *mutex);
Mutex example thread 1 thread 2 request_t *remove() { pthread_mutex_lock(&lock); ...sleeping... request = requests; requests = requests->next; pthread_mutex_unlock(&lock) return(request); } add(request_t *request) { pthread_mutex_lock(&lock); request->next = requests; requests = request pthread_mutex_unlock(&lock); }
Semaphores A counting semaphore6 is a variable that youcan increment arbitrarily high, but decrement only to zero. A sem_post()operation increments the semaphore, while asem_wait() attempts to decrement it. If thesemaphore is greater than zero, the operation succeeds; if not, then the callingthread must go to sleep until a different thread increments it.
Semaphores initialisation NAME sem_init, sem_destroy- initializes the semaphore to value. If pshared is non-zero,then the semaphore will be sharable among processes.This destroys the semaphore. SYNOPSIS #include <pthread.h> int sem_init(sem_t *sem, int pshared, unsigned int value);int sem_destroy(sem_t *sem);
Semaphores operations NAME sem_post,sem_wait, sem_trywait- function increments the value of the semaphore or decrements the value of sem by one. If the semaphore’s value is zero,sem_wait() blocks, waiting for the semaphore to be incremented byanother process or thread, while sem_trywait() will returnimmediately. SYNOPSIS #include <pthread.h> int sem_post(sem_t *sem); int sem_trywait(sem_t *sem); int sem_wait(sem_t *sem);
Semaphores operations NAME sem_open,sem_close- returns a pointer to the semaphore name. All processes which callthis on the same name will get the same semaphore pointer or closes the named semaphore for this process. SYNOPSIS #include <pthread.h> sem_t *sem_open(char *name, int oflag,... ); int sem_close(sem_t *sem);
Semaphors example request_t *get_request() {request_t *request; request = (request_t *) malloc(sizeof(request_t)); request->data = read_from_net(); return(request) } void process_request(request_t *request) { process(request->data); free(request); } producer() {request_t *request; while(1){ request = get_request(); add(request); sem_post(&requests_length); } } consumer() {request_t *request; while(1){SEM_WAIT(&requests_length); request = remove(); process_request(request); } }
Conditional Variable initialisation NAME pthread_cond_init, pthread_cond_destroy- initializes cond with att or destroys the condition variable, making it unusable in any form. SYNOPSIS #include <pthread.h> int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond);
Conditional Variable Wait Operation NAME pthread_cond_wait, pthread_cond_timewait- atomically releases mutex and causes the calling thread to block oncond. Upon successful return, the mutex will be reacquired. SYNOPSIS #include <pthread.h> int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec*abstime);
Conditional Variable Signal Operation NAME pthread_cond_signal,pthread_cond_broadcast- unblocks the first thread (if any) blocked on a condition variable or unblocks all threads blocked on a condition variable. You do not know the order in which they awake. SYNOPSIS #include <pthread.h> int pthread_cond_signal(pthread_cond_t *cond);int pthread_cond_broadcast(pthread_cond_t *cond);
Conditional Variable Example thread 1 thread 2 pthread_mutex_lock(&m); my_condition = TRUE; pthread_mutex_unlock(&m); pthread_cond_signal(&c); pthread_mutex_lock(&m); while (!my_condition) pthread_cond_wait(&c, &m); ... sleeping ... do_thing() pthread_mutex_unlock(&m);
Conditional Variable Example void *producer(void *arg) {request_t *request; while(1) { request = get_request(); pthread_mutex_lock(&r_lock); while (length >= 10) pthread_cond_wait(&r_producer, &r_lock); add(request); length++;pthread_mutex_unlock(&r_lock); pthread_cond_signal(&r_consumer); } } void *consumer(void *arg) {request_t *request; while(1) {pthread_mutex_lock(&r_lock); while (length == 0) pthread_cond_wait(&r_consumer, &r_lock); request = remove(); length--; pthread_mutex_unlock(&r_lock); pthread_cond_signal(&r_producer); process_request(request); } }
Processes NAME CreateProcess - creates a new process and its primary thread. SYNOPSIS BOOL CreateProcess(LPCTSTRlpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOLbInheritHandles, DWORDdwCreationFlags, LPVOIDlpEnvironment, LPCTSTRlpCurrentDirectory, LPSTARTUPINFOlpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes Pointer to a null-terminated string that specifies the module to execute. NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTRlpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes Pointer to a null-terminated string that specifies the command line to execute. NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes If this parameter TRUE, each inheritable handle in the calling process is inherited by the new process. NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOLbInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes Additionalcreationflagse.g. CREATE_NEW_CONSOLE, CREATE_SUSPENDED, DETACHED_PROCESS NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOLbInheritHandles, DWORDdwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes A pointer to the environment block for the new process. NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOLbInheritHandles, DWORDdwCreationFlags, LPVOIDlpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes The full path to the current directory for the process. NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOLbInheritHandles, DWORDdwCreationFlags, LPVOIDlpEnvironment, LPCTSTRlpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes A pointer to a STARTUPINFO NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOLbInheritHandles, DWORDdwCreationFlags, LPVOIDlpEnvironment, LPCTSTRlpCurrentDirectory, LPSTARTUPINFOlpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Processes A pointer to a PROCESS_INFORMATION structure that receives identification information about the new process. NAME CreateProcess- creates a new process and its primary thread. SYNOPSIS BOOLCreateProcess( LPCTSTR lpApplicationName, LPTSTRlpCommandLine, LPSECURITY_ATTRIBUTESlpProcessAttributes, LPSECURITY_ATTRIBUTESlpThreadAttributes, BOOLbInheritHandles, DWORDdwCreationFlags, LPVOIDlpEnvironment, LPCTSTRlpCurrentDirectory, LPSTARTUPINFOlpStartupInfo, LPPROCESS_INFORMATIONlpProcessInformation );
Process example void _tmain( int argc, TCHAR *argv[] ) { STARTUPINFO si; PROCESS_INFORMATION pi; if( !CreateProcess( NULL, // No module name (use command line) argv[1], // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { printf( "CreateProcess failed (%d)\n", GetLastError() ); return; } // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); }
Threads NAME CreateThread- creates a thread to execute within the address space of the calling process. SYNOPSIS HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParam, DWORD fdwCreate, LPDWORD lpIDThread );
Threads A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. NAME CreateThread- creates a thread to execute within the address space of the calling process. SYNOPSIS HANDLECreateThread( LPSECURITY_ATTRIBUTESlpsa, DWORDcbStack, LPTHREAD_START_ROUTINElpStartAddr, LPVOIDlpvThreadParam, DWORDfdwCreate, LPDWORDlpIDThread );
Threads The initial size of the stack, in bytes. NAME CreateThread- creates a thread to execute within the address space of the calling process. SYNOPSIS HANDLECreateThread( LPSECURITY_ATTRIBUTESlpsa, DWORDcbStack, LPTHREAD_START_ROUTINElpStartAddr, LPVOIDlpvThreadParam, DWORDfdwCreate, LPDWORDlpIDThread );
Threads A pointer to the application-defined function to be executed by the thread and represents the starting address of the thread. DWORDThreadProc(LPVOIDlpParameter ); NAME CreateThread- creates a thread to execute within the address space of the calling process. SYNOPSIS HANDLECreateThread( LPSECURITY_ATTRIBUTESlpsa, DWORD cbStack, LPTHREAD_START_ROUTINElpStartAddr, LPVOIDlpvThreadParam, DWORDfdwCreate, LPDWORDlpIDThread );
Threads A pointer to a variable to be passed to the thread. NAME CreateThread- creates a thread to execute within the address space of the calling process. SYNOPSIS HANDLECreateThread( LPSECURITY_ATTRIBUTESlpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOIDlpvThreadParam, DWORDfdwCreate, LPDWORDlpIDThread );
Threads The flags that control the creation of the threadi.e.CREATE_SUSPENDED. NAME CreateThread- creates a thread to execute within the address space of the calling process. SYNOPSIS HANDLECreateThread( LPSECURITY_ATTRIBUTESlpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParam, DWORDfdwCreate, LPDWORDlpIDThread );
Threads A pointer to a variable that receives the thread identifier. NAME CreateThread- creates a thread to execute within the address space of the calling process. SYNOPSIS HANDLECreateThread( LPSECURITY_ATTRIBUTESlpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParam, DWORD fdwCreate, LPDWORDlpIDThread );
Threads - Example int _tmain() { PMYDATApData[MAX_THREADS]; DWORDdwThreadId[MAX_THREADS]; HANDLEhThread[MAX_THREADS]; inti; for( i=0; i<MAX_THREADS; i++ ) { pData[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MYDATA)); pData->val1 = i; pData->val2 = i+100; hThread[i] = CreateThread( NULL, // default security attributes 0, // use default stack size MyThread, // thread function pData, // argument to thread function 0, // use default creation flags &dwThreadId[i]); // returns the thread identifier }} WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE); // Close all thread handles and free memory allocation. for(i=0; i<MAX_THREADS; i++) { CloseHandle(hThread[i]); } HeapFree(GetProcessHeap(), 0, pData[i]); return 0; }
What is wrong with CreateThread function ? A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread
_beginthreadex NAME _beginthreadex - creates a thread to execute within the address space of the calling process. SYNOPSIS uintptr_t _beginthreadex( void *security, unsigned stack_size, unsigned ( *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr );
_beginthreadex Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. NAME _beginthreadex - creates a thread to execute within the address space of the calling process. SYNOPSIS uintptr_t _beginthreadex( void *security, unsignedstack_size, unsigned ( *start_address )( void * ), void *arglist, unsignedinitflag, unsigned *thrdaddr );
_beginthreadex Stack size for a new thread or 0. NAME _beginthreadex - creates a thread to execute within the address space of the calling process. SYNOPSIS uintptr_t _beginthreadex( void *security, unsignedstack_size, unsigned ( *start_address )( void * ), void *arglist, unsignedinitflag, unsigned *thrdaddr );
_beginthreadex Start address of a routine that begins execution of a new thread. NAME _beginthreadex - creates a thread to execute within the address space of the calling process. SYNOPSIS uintptr_t _beginthreadex( void *security, unsignedstack_size, unsigned( *start_address )(void* ), void *arglist, unsignedinitflag, unsigned *thrdaddr );
_beginthreadex Argument list to be passed to a new thread. NAME _beginthreadex - creates a thread to execute within the address space of the calling process. SYNOPSIS uintptr_t _beginthreadex( void *security, unsignedstack_size, unsigned ( *start_address )( void * ), void*arglist, unsignedinitflag, unsigned *thrdaddr );
_beginthreadex Argument list to be passed to a new thread. NAME _beginthreadex - creates a thread to execute within the address space of the calling process. SYNOPSIS uintptr_t _beginthreadex( void *security, unsignedstack_size, unsigned ( *start_address )( void * ), void *arglist, unsignedinitflag, unsigned *thrdaddr );
_beginthreadex Points to a 32-bit variable that receives the thread identifierlist to be passed to a new thread. NAME _beginthreadex - creates a thread to execute within the address space of the calling process. SYNOPSIS uintptr_t _beginthreadex( void *security, unsignedstack_size, unsigned ( *start_address )( void * ), void *arglist, unsigned initflag, unsigned*thrdaddr );
_beginthreadex example int main() { HANDLEhThread; unsignedthreadID; printf( "Creating second thread...\n" ); hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID ); WaitForSingleObject( hThread, INFINITE ); CloseHandle( hThread ); }