123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /*
- * semaphore.c
- *
- * Copyright (C) 2016 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <semaphore.h>
- #include <thread.h>
- #include <heap.h>
- void init_semaphore(semaphore_t *semaphore, dword_t init_count, dword_t max_count)
- {
- ASSERT(init_count <= max_count);
- semaphore->count = init_count;
- semaphore->max_count = max_count;
- }
- sysret_t syscall_create_semaphore(const char *name, dword_t init_count, dword_t max_count, handle_t *handle)
- {
- handle_t safe_handle;
- char *safe_name = NULL;
- if ((max_count == 0) || (init_count > max_count)) return ERR_INVALID;
- semaphore_t *semaphore = (semaphore_t*)malloc(sizeof(semaphore_t));
- if (semaphore == NULL) return ERR_NOMEMORY;
- if (name != NULL)
- {
- if (get_previous_mode() == USER_MODE) safe_name = copy_user_string(name);
- else safe_name = (char*)name;
- }
- init_semaphore(semaphore, init_count, max_count);
- init_object(&semaphore->header, name, OBJECT_SEMAPHORE);
- dword_t ret = create_object(&semaphore->header);
- if (ret != ERR_SUCCESS)
- {
- if (semaphore->header.name) free(semaphore->header.name);
- free(semaphore);
- return ret;
- }
- ret = open_object(&semaphore->header, 0, &safe_handle);
- dereference(&semaphore->header);
- if (ret == ERR_SUCCESS)
- {
- EH_TRY *handle = safe_handle;
- EH_CATCH ret = ERR_BADPTR;
- EH_DONE;
- }
- if (get_previous_mode() == USER_MODE) free(safe_name);
- return ret;
- }
- sysret_t syscall_open_semaphore(const char *name, handle_t *handle)
- {
- handle_t safe_handle;
- char *safe_name = NULL;
- if (get_previous_mode() == USER_MODE)
- {
- dword_t name_length = 0;
- EH_TRY name_length = strlen(name);
- EH_CATCH EH_ESCAPE(return ERR_BADPTR);
- EH_DONE;
- if (!check_usermode(name, name_length + 1)) return ERR_BADPTR;
- if (!check_usermode(handle, sizeof(handle_t))) return ERR_BADPTR;
- safe_name = copy_user_string(name);
- if (safe_name == NULL) return ERR_BADPTR;
- }
- else safe_name = (char*)name;
- dword_t ret = open_object_by_name(safe_name, OBJECT_SEMAPHORE, 0, &safe_handle);
- EH_TRY *handle = safe_handle;
- EH_CATCH
- {
- syscall_close_object(safe_handle);
- ret = ERR_BADPTR;
- }
- EH_DONE;
- if (get_previous_mode() == USER_MODE) free(safe_name);
- return ret;
- }
- dword_t wait_semaphore(semaphore_t *semaphore, dword_t count, dword_t timeout)
- {
- if (count > semaphore->max_count) return ERR_INVALID;
- if (semaphore->count < count)
- {
- dword_t ret = scheduler_wait(WAIT_UNTIL_NOT_LESS, timeout, &semaphore->count, count);
- if (ret == WAIT_TIMED_OUT) return ERR_TIMEOUT;
- else if (ret == WAIT_CANCELED) return ERR_CANCELED;
- }
- semaphore->count -= count;
- return ERR_SUCCESS;
- }
- dword_t release_semaphore(semaphore_t *semaphore, dword_t count)
- {
- if ((semaphore->count + count) <= semaphore->max_count)
- {
- semaphore->count += count;
- if (scheduler_enabled) syscall_yield_quantum();
- return ERR_SUCCESS;
- }
- else
- {
- return ERR_INVALID;
- }
- }
- sysret_t syscall_wait_semaphore(handle_t semaphore, dword_t count, dword_t timeout)
- {
- semaphore_t *obj;
- if (!reference_by_handle(semaphore, OBJECT_SEMAPHORE, (object_t**)&obj)) return ERR_INVALID;
- dword_t ret = wait_semaphore(obj, count, timeout);
- dereference(&obj->header);
- return ret;
- }
- sysret_t syscall_release_semaphore(handle_t semaphore, dword_t count)
- {
- semaphore_t *obj;
- if (!reference_by_handle(semaphore, OBJECT_SEMAPHORE, (object_t**)&obj)) return ERR_INVALID;
- release_semaphore(obj, count);
- dereference(&obj->header);
- return ERR_SUCCESS;
- }
|