10.07.2015 Views

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

B.4. PER-THREAD VARIABLES 1591 int main(int argc, char *argv[])2 {3 int i;4 int nkids = 1;56 smp_init();7 if (argc > 1) {8 nkids = strtoul(argv[1], NULL, 0);9 if (nkids > NR_THREADS) {10 fprintf(stderr, "nkids=%d too big, max=%d\n",11 nkids, NR_THREADS);12 usage(argv[0]);13 }14 }15 printf("Parent spawning %d threads.\n", nkids);16 for (i = 0; i < nkids; i++)17 create_thread(thread_test, (void *)i);18 wait_all_threads();19 printf("All threads completed.\n", nkids);20 exit(0);21 }Figure B.3: Example Parent ThreadB.3 LockingThe locking API is shown in Figure B.4, each APIelement being described in the following sections.void spin_lock_init(spinlock_t *sp);void spin_lock(spinlock_t *sp);int spin_trylock(spinlock_t *sp);void spin_unlock(spinlock_t *sp);Figure B.4: Locking APIB.3.1 spin lock init()The spin_lock_init() primitive initializes thespecified spinlock_t variable, and must be invokedbefore this variable is passed to any other spinlockprimitive.B.3.2 spin lock()The spin_lock() primitive acquires the specifiedspinlock, if necessary, waiting until the spinlock becomesavailable. In some environments, such aspthreads, this waiting will involve “spinning”, whilein others, such as the Linux kernel, it will involveblocking.The key point is that only one thread may hold aspinlock at any given time.B.3.3 spin trylock()The spin_trylock() primitive acquires the specifiedspinlock, but only if it is immediately available.<strong>It</strong> returns TRUE if it was able to acquire the spinlockand FALSE otherwise.B.3.4 spin unlock()The spin_unlock() primitive releases the specifiedspinlock, allowing other threads to acquire it.@@@ likely need to add reader-writer locking.B.3.5 Example UsageA spinlock named mutex may be used to protect avariable counter as follows:spin_lock(&mutex);counter++;spin_unlock(&mutex);Quick Quiz B.2: <strong>What</strong> problems could occur ifthe variable counter were incremented without theprotection of mutex?However, the spin_lock() and spin_unlock()primitivesdohaveperformanceconsequences,aswillbe seen in Section B.5.B.4 Per-Thread VariablesFigure B.5 shows the per-thread-variable API. ThisAPI provides the per-thread equivalent of globalvariables. Although this API is, strictly speaking,not necessary, it can greatly simply coding.DEFINE_PER_THREAD(type, name)DECLARE_PER_THREAD(type, name)per_thread(name, thread)__get_thread_var(name)init_per_thread(name, v)Figure B.5: Per-Thread-Variable APIQuick Quiz B.3: How could you work aroundthe lack of a per-thread-variable API on systemsthat do not provide it?B.4.1 DEFINE PER THREAD()The DEFINE_PER_THREAD() primitive defines a perthreadvariable. Unfortunately, it is not possible toprovide an initializer in the way permitted by theLinux kernel’s DEFINE_PER_THREAD() primitive, butthere is an init_per_thread() primitive that permitseasy runtime initialization.B.4.2 DECLARE PER THREAD()The DECLARE_PER_THREAD() primitive is a declarationin the C sense, as opposed to a definition. Thus,a DECLARE_PER_THREAD() primitive may be used toaccess a per-thread variable defined in some otherfile.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!