00001 /* 00002 * Copyright (c) 2006 Jakub Jermar 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * - Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * - Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * - The name of the author may not be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00018 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00019 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00020 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00035 #include <thread.h> 00036 #include <libc.h> 00037 #include <stdlib.h> 00038 #include <libarch/faddr.h> 00039 #include <kernel/proc/uarg.h> 00040 #include <fibril.h> 00041 #include <str.h> 00042 #include <async.h> 00043 #include "private/thread.h" 00044 00045 #ifndef THREAD_INITIAL_STACK_PAGES_NO 00046 #define THREAD_INITIAL_STACK_PAGES_NO 2 00047 #endif 00048 00058 void __thread_main(uspace_arg_t *uarg) 00059 { 00060 fibril_t *fibril = fibril_setup(); 00061 if (fibril == NULL) 00062 thread_exit(0); 00063 00064 __tcb_set(fibril->tcb); 00065 00066 uarg->uspace_thread_function(uarg->uspace_thread_arg); 00067 /* XXX: we cannot free the userspace stack while running on it 00068 free(uarg->uspace_stack); 00069 free(uarg); 00070 */ 00071 00072 /* If there is a manager, destroy it */ 00073 async_destroy_manager(); 00074 fibril_teardown(fibril); 00075 00076 thread_exit(0); 00077 } 00078 00091 int thread_create(void (* function)(void *), void *arg, const char *name, 00092 thread_id_t *tid) 00093 { 00094 char *stack; 00095 uspace_arg_t *uarg; 00096 int rc; 00097 00098 stack = (char *) malloc(getpagesize() * THREAD_INITIAL_STACK_PAGES_NO); 00099 if (!stack) 00100 return -1; 00101 00102 uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t)); 00103 if (!uarg) { 00104 free(stack); 00105 return -1; 00106 } 00107 00108 uarg->uspace_entry = (void *) FADDR(__thread_entry); 00109 uarg->uspace_stack = (void *) stack; 00110 uarg->uspace_thread_function = function; 00111 uarg->uspace_thread_arg = arg; 00112 uarg->uspace_uarg = uarg; 00113 00114 rc = __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name, 00115 (sysarg_t) str_size(name), (sysarg_t) tid); 00116 00117 if (rc) { 00118 /* 00119 * Failed to create a new thread. 00120 * Free up the allocated structures. 00121 */ 00122 free(uarg); 00123 free(stack); 00124 } 00125 00126 return rc; 00127 } 00128 00134 void thread_exit(int status) 00135 { 00136 __SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status); 00137 00138 /* Unreachable */ 00139 while (1); 00140 } 00141 00148 void thread_detach(thread_id_t thread) 00149 { 00150 } 00151 00160 int thread_join(thread_id_t thread) 00161 { 00162 return 0; 00163 } 00164 00169 thread_id_t thread_get_id(void) 00170 { 00171 thread_id_t thread_id; 00172 00173 (void) __SYSCALL1(SYS_THREAD_GET_ID, (sysarg_t) &thread_id); 00174 00175 return thread_id; 00176 } 00177