/* Test mutex */ static int test_mutex(void){ sync_mutex_t m1, m2; printf("UNIT TEST | sync/mutex: "); m1 = sync_create_mutex(); test_assert(m1); m2 = sync_create_mutex(); test_assert(m2); /* Test simple operations */ test_assert(sync_try_acquire(m1)); test_assert(!sync_try_acquire(m1)); sync_release(m1); test_assert(sync_try_acquire(m1)); sync_release(m1); sync_acquire(m1); sync_release(m1); sync_acquire(m1); sync_release(m1); /* Test independance */ test_assert(sync_try_acquire(m1)); test_assert(sync_try_acquire(m2)); sync_release(m1); sync_release(m2); /* Clean up */ sync_destroy_mutex(m1); sync_destroy_mutex(m2); printf("PASSED\n"); return 0; }
int sys_sync_create_object(sync_object_type_t obj_type, void *uobj,uint8_t *attrs, ulong_t flags) { kern_sync_object_t *kobj=NULL; int r; sync_id_t id; task_t *caller=current_task(); uint8_t shared; task_sync_data_t *sync_data; if( !s_check_system_capability(SYS_CAP_SYNC) ) { return ERR(-EPERM); } if( !uobj || obj_type > __SO_MAX_TYPE ) { return ERR(-EINVAL); } if( !attrs ) { shared=0; } else { if( get_user(shared,attrs) ) { return ERR(-EINVAL); } if( shared != PTHREAD_PROCESS_PRIVATE && shared != PTHREAD_PROCESS_SHARED ) { return ERR(-EINVAL); } } sync_data=get_task_sync_data(caller); if( !sync_data ) { return ERR(-EAGAIN); } LOCK_SYNC_DATA_W(sync_data); r=__sync_allocate_id(caller,shared,&id); if( r ) { goto put_sync_data; } UNLOCK_SYNC_DATA_W(sync_data); switch( obj_type ) { case __SO_MUTEX: r=sync_create_mutex(&kobj,uobj,attrs,flags); break; case __SO_RAWEVENT: r=sync_create_uevent(&kobj,uobj,attrs,flags); break; case __SO_RWSEMAPHORE: r=sync_create_urw_semaphore(&kobj,uobj,attrs,flags); break; case __SO_CONDVAR: case __SO_SEMAPHORE: default: r=-EINVAL; break; } /* Copy ID to user without holding the lock for better performance. */ if( !r ) { r=copy_to_user(uobj,&id,sizeof(id)); } LOCK_SYNC_DATA_W(sync_data); if( r ) { goto put_id; } __install_sync_object(caller,kobj,id); UNLOCK_SYNC_DATA_W(sync_data); return 0; put_id: __sync_free_id(caller,id); put_sync_data: UNLOCK_SYNC_DATA_W(sync_data); /* Free object, if any. */ if( kobj ) { sync_put_object(kobj); } release_task_sync_data(sync_data); return ERR(r); }