int ipc_sem_get_value(sem_t sem_id, int *value_store) { assert(current->sem_queue != NULL); if (value_store == NULL) { return -E_INVAL; } struct mm_struct *mm = current->mm; if (!user_mem_check(mm, (uintptr_t)value_store, sizeof(int), 1)) { return -E_INVAL; } sem_undo_t *semu; sem_queue_t *sem_queue = current->sem_queue; down(&(sem_queue->sem)); semu = semu_list_search(&(sem_queue->semu_list), sem_id); up(&(sem_queue->sem)); int ret = -E_INVAL; if (semu != NULL) { int value = semu->sem->value; lock_mm(mm); { if (copy_to_user(mm, value_store, &value, sizeof(int))) { ret = 0; } } unlock_mm(mm); } return ret; }
int ipc_sem_post(sem_t sem_id) { assert(current->sem_queue != NULL); sem_undo_t *semu; sem_queue_t *sem_queue = current->sem_queue; down(&(sem_queue->sem)); semu = semu_list_search(&(sem_queue->semu_list), sem_id); up(&(sem_queue->sem)); if (semu != NULL) { return usem_up(semu->sem); } return -E_INVAL; }
int ipc_sem_wait(sem_t sem_id, unsigned int timeout) { assert(current->sem_queue != NULL); sem_undo_t *semu; sem_queue_t *sem_queue = current->sem_queue; down(&(sem_queue->sem)); semu = semu_list_search(&(sem_queue->semu_list), sem_id); up(&(sem_queue->sem)); if (semu != NULL) { return usem_down(semu->sem, timeout); } return -E_INVAL; }
int ipc_sem_post_max(sem_t sem_id, int max) { assert(pls_read(current)->sem_queue != NULL); sem_undo_t *semu; sem_queue_t *sem_queue = pls_read(current)->sem_queue; down(&(sem_queue->sem)); semu = semu_list_search(&(sem_queue->semu_list), sem_id); up(&(sem_queue->sem)); if(semu != NULL) { int i; int ret = 0; for(i = 0; i < max; ++i) { if(wait_queue_empty(&(semu->sem->wait_queue))) break; usem_up(semu->sem); ++ret; } return ret; } return -E_INVAL; }
int ipc_sem_free(sem_t sem_id) { assert(current->sem_queue != NULL); sem_undo_t *semu; sem_queue_t *sem_queue = current->sem_queue; down(&(sem_queue->sem)); semu = semu_list_search(&(sem_queue->semu_list), sem_id); up(&(sem_queue->sem)); int ret = -E_INVAL; if (semu != NULL) { bool intr_flag; local_intr_save(intr_flag); { semaphore_t *sem = semu->sem; sem->valid = 0, ret = 0; wakeup_queue(&(sem->wait_queue), WT_INTERRUPTED, 1); } local_intr_restore(intr_flag); } return ret; }