void _init_top(void) { ASSERT(top_init_debug()); /* * set up the delta layer */ _init_map(); /* * Initialise the thread specific data transaction key */ tsd_create(&topkey, top_threadtrans_destroy); }
/* * Create threads which set and verify SPLAT_THREAD_TEST_KEYS number of * keys. These threads may then exit by calling thread_exit() which calls * tsd_exit() resulting in all their thread specific data being reclaimed. * Alternately, the thread may block in which case the thread specific * data will be reclaimed as part of tsd_destroy(). In either case all * thread specific data must be reclaimed, this is verified by ensuring * the registered destructor is called the correct number of times. */ static int splat_thread_test3(struct file *file, void *arg) { int i, rc = 0, expected, wait_count = 0, exit_count = 0; thread_priv_t tp; tp.tp_magic = SPLAT_THREAD_TEST_MAGIC; tp.tp_file = file; spin_lock_init(&tp.tp_lock); init_waitqueue_head(&tp.tp_waitq); tp.tp_rc = 0; tp.tp_count = 0; tp.tp_dtor_count = 0; for (i = 0; i < SPLAT_THREAD_TEST_KEYS; i++) { tp.tp_keys[i] = 0; tsd_create(&tp.tp_keys[i], splat_thread_dtor3); } /* Start tsd wait threads */ for (i = 0; i < SPLAT_THREAD_TEST_THREADS; i++) { if (thread_create(NULL, 0, splat_thread_work3_wait, &tp, 0, &p0, TS_RUN, defclsyspri)) wait_count++; } /* All wait threads have setup their tsd and are blocking. */ wait_event(tp.tp_waitq, splat_thread_count(&tp, wait_count)); if (tp.tp_dtor_count != 0) { splat_vprint(file, SPLAT_THREAD_TEST3_NAME, "Prematurely ran %d tsd destructors\n", tp.tp_dtor_count); if (!rc) rc = -ERANGE; } /* Start tsd exit threads */ for (i = 0; i < SPLAT_THREAD_TEST_THREADS; i++) { if (thread_create(NULL, 0, splat_thread_work3_exit, &tp, 0, &p0, TS_RUN, defclsyspri)) exit_count++; } /* All exit threads verified tsd and are in the process of exiting */ wait_event(tp.tp_waitq,splat_thread_count(&tp, wait_count+exit_count)); msleep(500); expected = (SPLAT_THREAD_TEST_KEYS * exit_count); if (tp.tp_dtor_count != expected) { splat_vprint(file, SPLAT_THREAD_TEST3_NAME, "Expected %d exit tsd destructors but saw %d\n", expected, tp.tp_dtor_count); if (!rc) rc = -ERANGE; } /* Destroy all keys and associated tsd in blocked threads */ for (i = 0; i < SPLAT_THREAD_TEST_KEYS; i++) tsd_destroy(&tp.tp_keys[i]); expected = (SPLAT_THREAD_TEST_KEYS * (exit_count + wait_count)); if (tp.tp_dtor_count != expected) { splat_vprint(file, SPLAT_THREAD_TEST3_NAME, "Expected %d wait+exit tsd destructors but saw %d\n", expected, tp.tp_dtor_count); if (!rc) rc = -ERANGE; } /* Release the remaining wait threads, sleep briefly while they exit */ spin_lock(&tp.tp_lock); tp.tp_count = 0; wake_up_all(&tp.tp_waitq); spin_unlock(&tp.tp_lock); msleep(500); if (tp.tp_rc) { splat_vprint(file, SPLAT_THREAD_TEST3_NAME, "Thread tsd_get()/tsd_set() error %d\n", tp.tp_rc); if (!rc) rc = tp.tp_rc; } else if (!rc) { splat_vprint(file, SPLAT_THREAD_TEST3_NAME, "%s", "Thread specific data verified\n"); } return rc; }