#include "ks.h" #include "tap.h" #define MAX_STUFF 200 static ks_thread_t *threads[MAX_STUFF]; static ks_thread_t *thread_p; static ks_pool_t *pool; static ks_mutex_t *mutex; static ks_mutex_t *mutex_non_recursive; static ks_rwl_t *rwlock; static ks_cond_t *cond; static int counter1 = 0; static int counter2 = 0; static int counter3 = 0; static int counter4 = 0; static int counter5 = 0; static int counter6 = 0; static int threadscount = 0; static int cpu_count = 0; #define LOOP_COUNT 10000 static void *thread_priority(ks_thread_t *thread, void *data) { while (thread->running) { ks_sleep(1000000); } return NULL; } static void *thread_test_cond_producer_func(ks_thread_t *thread, void *data) { for (;;) { ks_cond_lock(cond); if (counter5 >= LOOP_COUNT) { ks_cond_unlock(cond); break; } counter5++; if (counter6 == 0) { ks_cond_signal(cond); } counter6++; ks_cond_unlock(cond); *((int *) data) += 1; } return NULL; } static void *thread_test_cond_consumer_func(ks_thread_t *thread, void *data) { int i; for (i = 0; i < LOOP_COUNT; i++) { ks_cond_lock(cond); while (counter6 == 0) { ks_cond_wait(cond); } counter6--; ks_cond_unlock(cond); } return NULL; } static void check_cond(void) { int count[MAX_STUFF] = { 0 }; int ttl = 0; ok( (ks_pool_open(&pool) == KS_STATUS_SUCCESS) ); ok( (ks_cond_create(&cond, pool) == KS_STATUS_SUCCESS) ); int i; for(i = 0; i < cpu_count; i++) { ok( (ks_thread_create(&threads[i], thread_test_cond_producer_func, &count[i], pool) == KS_STATUS_SUCCESS) ); } ok( (ks_thread_create(&thread_p, thread_test_cond_consumer_func, NULL, pool) == KS_STATUS_SUCCESS) ); ok( (ks_pool_close(&pool) == KS_STATUS_SUCCESS) ); for(i = 0; i < cpu_count; i++) { ttl += count[i]; } ok( (ttl == LOOP_COUNT) ); } static void *thread_test_rwlock_func(ks_thread_t *thread, void *data) { int loop = 1; while (1) { ks_rwl_read_lock(rwlock); if (counter4 == LOOP_COUNT) { loop = 0; } ks_rwl_read_unlock(rwlock); if (!loop) { break; } ks_rwl_write_lock(rwlock); if (counter4 != LOOP_COUNT) { counter4++; } ks_rwl_write_unlock(rwlock); } return NULL; } static void check_rwl(void) { ks_status_t status; ok( (ks_pool_open(&pool) == KS_STATUS_SUCCESS) ); ok( (ks_rwl_create(&rwlock, pool) == KS_STATUS_SUCCESS) ); ks_rwl_read_lock(rwlock); status = ks_rwl_try_read_lock(rwlock); ok( status == KS_STATUS_SUCCESS ); if ( status == KS_STATUS_SUCCESS ) { ks_rwl_read_unlock(rwlock); } ks_rwl_read_unlock(rwlock); int i; for(i = 0; i < cpu_count; i++) { ok( (ks_thread_create(&threads[i], thread_test_rwlock_func, NULL, pool) == KS_STATUS_SUCCESS) ); } for(i = 0; i < cpu_count; i++) { ks_thread_join(threads[i]); } ok( (ks_pool_close(&pool) == KS_STATUS_SUCCESS) ); ok( (counter4 == LOOP_COUNT) ); } static void *thread_test_function_cleanup(ks_thread_t *thread, void *data) { int d = (int)(intptr_t)data; while (thread->running) { ks_sleep(1000000); } if ( d == 1 ) { ks_mutex_lock(mutex); counter3++; ks_mutex_unlock(mutex); } return NULL; } static void *thread_test_function_detatched(ks_thread_t *thread, void *data) { int i; int d = (int)(intptr_t)data; for (i = 0; i < LOOP_COUNT; i++) { ks_mutex_lock(mutex); if (d == 1) { counter2++; } ks_mutex_unlock(mutex); } ks_mutex_lock(mutex); threadscount++; ks_mutex_unlock(mutex); return NULL; } static void *thread_test_function_atatched(ks_thread_t *thread, void *data) { int i; int d = (int)(intptr_t)data; void *mem, *last_mem = NULL; for (i = 0; i < LOOP_COUNT; i++) { if (last_mem) { ks_pool_free(thread->pool, &last_mem); } mem = ks_pool_alloc(thread->pool, 1024); last_mem = mem; } for (i = 0; i < LOOP_COUNT; i++) { ks_mutex_lock(mutex); if (d == 1) { counter1++; } ks_mutex_unlock(mutex); } return NULL; } static void create_threads_cleanup(void) { void *d = (void *)(intptr_t)1; int i; for(i = 0; i < cpu_count; i++) { ok( (ks_thread_create(&threads[i], thread_test_function_cleanup, d, pool) == KS_STATUS_SUCCESS) ); } } static void create_threads_atatched(void) { void *d = (void *)(intptr_t)1; int i; for(i = 0; i < cpu_count; i++) { ok( (ks_thread_create(&threads[i], thread_test_function_atatched, d, pool) == KS_STATUS_SUCCESS) ); } } static void create_threads_detatched(void) { ks_status_t status; void *d = (void *)(intptr_t)1; int i; for(i = 0; i < cpu_count; i++) { status = ks_thread_create_ex(&threads[i], thread_test_function_detatched, d, KS_THREAD_FLAG_DETATCHED, KS_THREAD_DEFAULT_STACK, KS_PRI_NORMAL, pool); ok( status == KS_STATUS_SUCCESS ); } } static void check_thread_priority(void) { ks_status_t status; void *d = (void *)(intptr_t)1; status = ks_thread_create_ex(&thread_p, thread_priority, d, KS_THREAD_FLAG_DETATCHED, KS_THREAD_DEFAULT_STACK, KS_PRI_IMPORTANT, pool); ok( status == KS_STATUS_SUCCESS ); ks_sleep(1000000); todo("Add check to see if has permission to set thread priority\n"); ok( ks_thread_priority(thread_p) == KS_PRI_IMPORTANT ); end_todo; ks_pool_free(pool, &thread_p); } static void join_threads(void) { int i; for(i = 0; i < cpu_count; i++) { ok( (KS_STATUS_SUCCESS == ks_thread_join(threads[i])) ); } } static void check_atatched(void) { ok( counter1 == (LOOP_COUNT * cpu_count) ); } static void check_detached(void) { ok( counter2 == (LOOP_COUNT * cpu_count) ); } static void create_pool(void) { ok( (ks_pool_open(&pool) == KS_STATUS_SUCCESS) ); } static void check_cleanup(void) { ok( (counter3 == cpu_count) ); } static void check_pool_close(void) { ok( (ks_pool_close(&pool) == KS_STATUS_SUCCESS) ); } static void create_mutex(void) { ok( (ks_mutex_create(&mutex, KS_MUTEX_FLAG_DEFAULT, pool) == KS_STATUS_SUCCESS) ); } static void create_mutex_non_recursive(void) { ok( (ks_mutex_create(&mutex_non_recursive, KS_MUTEX_FLAG_NON_RECURSIVE, pool) == KS_STATUS_SUCCESS) ); } static void test_recursive_mutex(void) { ks_status_t status; ks_mutex_lock(mutex); status = ks_mutex_trylock(mutex); if (status == KS_STATUS_SUCCESS) { ks_mutex_unlock(mutex); } ok(status == KS_STATUS_SUCCESS); ks_mutex_unlock(mutex); } static void test_non_recursive_mutex(void) { ks_status_t status; ks_mutex_lock(mutex_non_recursive); status = ks_mutex_trylock(mutex_non_recursive); if (status == KS_STATUS_SUCCESS) { ks_mutex_unlock(mutex_non_recursive); } ok(status != KS_STATUS_SUCCESS); ks_mutex_unlock(mutex_non_recursive); } int main(int argc, char **argv) { ks_init(); cpu_count = ks_cpu_count() * 4; plan(21 + cpu_count * 6); diag("Starting testing for %d tests\n", 44); create_pool(); create_mutex(); create_mutex_non_recursive(); test_recursive_mutex(); test_non_recursive_mutex(); check_thread_priority(); create_threads_atatched(); join_threads(); check_atatched(); create_threads_detatched(); while (threadscount != cpu_count) ks_sleep(1000000); check_detached(); create_threads_cleanup(); check_pool_close(); check_cleanup(); check_rwl(); check_cond(); ks_shutdown(); done_testing(); }