• Like
Sysprog 14
Upcoming SlideShare
Loading in...5
×

Sysprog 14

  • 1,518 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,518
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
35
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. C/C++ Linux System Programming
      • Session 14
      • User-space System Programming
      • – session 4
  • 2. Outline
    • Threads: Concepts and Linux Implementation
    • Creation and Termination
    • Cancellation
    • Mutual Exclusion and Threads
    • Process vs. Threads
  • 3. Threads
    • A lightweight process:
      • Share address space (unlike process)
      • Another execution context (like a process)
    • Why?
      • IPC
      • Dedicated (blocking) listener: Consider IPC or Device case
  • 4. Linux Implementation of Threads
    • Clone system call:
      • Part of a thread group (2.6):
        • all have same TGID (PID)
        • Have separate TID (gettid)
        • Same signal dispositions (separate masks)
        • Any thread can wait for the child of any other thread
        • A common VM
      • Ability to pass start of exec stack
    • Scheduled and context-switched as processes
    • Rest is in User-space (libpthread.so)
  • 5. Pthread Object “Template”:
    • pthread_xxx_t
    • int pthread_xxx_init (pthread_xxx_t *obj, pthread_xxxattr_t *attr);
    • int pthread_xxx_destroy (pthread_xxx_t *obj);
  • 6. Attribute Objects “Template”:
    • Initialization/Deletion of type xxx:
      • int pthread_xxxattr_destroy(pthread_xxxattr_t *attr);
      • int pthread_xxxattr_init(pthread_xxxattr_t *attr);
    • get/set attribute type xxx, attribute aaa:
      • int pthread_xxxattr_getaaa(pthread_xxxattr_t *attr, int *val);
      • int pthread_xxxattr_setaaa(pthread_xxxattr_t *attr, int val);
  • 7. Thread creation / termination
    • int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void*), void *restrict arg);
    • void pthread_exit(void *value_ptr);
    • Thread attributes (pthread_attr_t)
    • pthread_t – opaque identifier:
      • pthread_t pthread_self(void);
      • int pthread_equal(pthread_t t1, pthread_t t2);
  • 8. Reaping
    • Wait equivalent (from any thread not just creator):
      • int pthread_join(pthread_t thread, void **value_ptr);
    • To dodge reaping:
      • int pthread_detach(pthread_t thread);
    • PTHREAD_CREATE_DETACHED:
      • No need to reap (reaping would fail)
  • 9. Thread Specific Data
    • Need some memory to appear differently to different threads
    • Memory is keyed, key created/deleted once:
      • int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); // before any thread uses it
      • int pthread_key_delete(pthread_key_t key); // after all threads are done with it
      • Destructor is thread specific
    • To retrieve/modify memory:
      • void *pthread_getspecific(pthread_key_t key);
      • int pthread_setspecific(pthread_key_t key, const void *value);
  • 10. Cancelling Threads
    • int pthread_cancel(pthread_t thread);
    • Asynchronous
      • not a signal
      • Cleanup handling only (unlike signals)
    • Order:
      • Cancel call
      • Cancellation point
      • Cleanup handlers
      • Thread-specific data destructors
  • 11. Cancellability:
    • For critical sections, can't cancel
      • int pthread_setcancelstate(int state, int *oldstate); // PTHREAD_CANCEL_ENABLE/DISABLE
    • For control over cancel-safe points
      • int pthread_setcanceltype(int type, int *oldtype); // PTHREAD_CANCEL_ASYNCHRONOUS/DEFERRED
      • To place a cancellation point:
        • void pthread_testcancel(void);
    • Push/pop mindset, call sets on “module” entry, and restore on “module” exit
  • 12. Cleanup Stack
    • void pthread_cleanup_pop(int execute);
    • void pthread_cleanup_push(void (*routine)(void*), void *arg);
    • Execution upon:
      • Exit
      • Cancel
      • Pop with non-zero execute
    • Both in same lexical scope
  • 13. static RETSIGTYPE sigexit_handler(int signum) { int i; nslcd_exitsignal=signum; /* cancel all running threads */ for (i=0;i<nslcd_cfg->ldc_threads;i++) if (pthread_cancel(nslcd_threads[i])) { } } static void worker_cleanup(void *arg) { MYLDAP_SESSION *session=(MYLDAP_SESSION *)arg; myldap_session_close(session); } static void *worker(void UNUSED(*arg)) { MYLDAP_SESSION *session; /* create a new LDAP session */ session=myldap_create_session(); /* clean up the session if we're done */ pthread_cleanup_push(worker_cleanup,session); /* start waiting for incoming connections */ while (1) { /* wait for a new connection */ acceptconnection(session); } pthread_cleanup_pop(1); return NULL; } int main(int argc,char *argv[]) { ... install_sighandler(SIGTERM,sigexit_handler); install_sighandler(SIGUSR1,sigexit_handler); install_sighandler(SIGUSR2,sigexit_handler); nslcd_threads= (pthread_t *)malloc(nslcd_cfg->ldc_threads*sizeof(pthread_t)); for (i=0;i<nslcd_cfg->ldc_threads;i++) { if (pthread_create(&nslcd_threads[i],NULL,worker,NULL)) { ... exit(EXIT_FAILURE); } } for (i=0;i<nslcd_cfg->ldc_threads;i++) { if (pthread_join(nslcd_threads[i],NULL)) { ... exit(EXIT_FAILURE); } } }
  • 14. Mutual Exclusion
    • Threads are much more prone to race conditions – why?
    • pthread_mutex_t
      • int pthread_mutex_lock(pthread_mutex_t *mutex);
      • int pthread_mutex_trylock(pthread_mutex_t *mutex);
      • int pthread_mutex_unlock(pthread_mutex_t *mutex);
    • pthread_mutex_t is strictly for mutual exclusion, not synchronization (unlike...?)
  • 15. Mutex Object: pthread_mutex
    • Initialization:
      • Static:
        • pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
      • Non-static:
        • int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
        • int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • 16. Mutex Types
    • Type Attribute Values
      • PTHREAD_MUTEX_DEFAULT: deadlock on double lock by same thread (fast)
      • PTHREAD_MUTEX_RECURSIVE: no deadlock, but same # of unlocks before release
      • PTHREAD_MUTEX_ERRORCHECK: error on double lock by same thread
  • 17. RT Attributes:
    • Protocol:
      • PTHREAD_PRIO_NONE
      • PTHREAD_PRIO_INHERIT: If a higher priority thread is blocked on this, execute at that its prio
      • PTHREAD_PRIO_PROTECT: Execute at max (mine, ceiling {all my other mutexes})
    • Prioceiling:
      • Highest possible priority to run at: should be > highest priority that locks this mutex
  • 18. Futex
    • An area in memory used for mutexing threads, atomic operations
    • Futex system call in contended cases
    • By mmapping this (MMAP_SHARED), we have full kernel support, thus
      • Sharing Attribute
  • 19. Another Mutex Object: Read/Write Locks
    • Multiple concurrent readers
    • only one writer allowed (Lock state)
    • Attributes: sharing
    • Read:
      • int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
      • int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
    • Write:
      • int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
      • int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
    • Unlock:
      • int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
  • 20. Condition Variables
    • Synchronization
    • pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    • Attributes: sharing
    • Always mutexed (why?)
    • Implicit cancellation point – upon cancel, do not consume
    • int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t mutex);
      • Atomically: release mutex and wait on condition, acquired on wakeup
    • int pthread_cond_broadcast(pthread_cond_t *cond); // all
    • Int pthread_cond_signal(pthread_cond_t *cond); // at least one
  • 21. static void PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) { /* Lock the queue mutex */ pthread_mutex_lock (&pQueue->pmMutex); pNode->pNext = NULL; if (pQueue->pTail != NULL) { pQueue->pTail->pNext = pNode; } pQueue->pTail = pNode; if (pQueue->pHead == NULL) { pQueue->pHead = pNode; } /* Increase the count of elements in the queue by one */ ++g_nQueueSize; /* Release the queue mutex */ pthread_mutex_unlock (&pQueue->pmMutex); /* Signal that the queue is not empty */ pthread_cond_signal (&pQueue->pcNotEmpty); } static WMMsgNodePtr PopMessage (WMMsgQueuePtr pQueue, WMInfoPtr pWMInfo) { /* Lock the queue mutex */ pthread_mutex_lock (&pQueue->pmMutex); /* Wait for --- */ while (pQueue->pHead == NULL) { pthread_cond_wait (&pQueue->pcNotEmpty, &pQueue->pmMutex); } pNode = pQueue->pHead; if (pQueue->pHead != NULL) { pQueue->pHead = pQueue->pHead->pNext; } if (pQueue->pTail == pNode) { pQueue->pTail = NULL; } /* Drop the number of elements in the queue by one */ --g_nQueueSize; /* Release the queue mutex */ pthread_mutex_unlock (&pQueue->pmMutex); return pNode; }
  • 22. Process vs Thread
    • Ease of communication
    • Creation overhead
    • Potential for race conditions
    • Vulnerability coupling
    • SMP systems