some further WIP polish localization.
[AROS.git] / compiler / pthread / pthread_create.c
blob00b2b3fc788289fe81be1f11260306c43b7d0ff7
1 /*
2 Copyright (C) 2014 Szilard Biro
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
21 #include <proto/exec.h>
22 #include <proto/dos.h>
24 #include <stdio.h>
26 #include "pthread_intern.h"
27 #include "debug.h"
29 static void StarterFunc(void)
31 ThreadInfo *inf;
32 int i, j;
33 int foundkey = TRUE;
34 #ifdef USE_ASYNC_CANCEL
35 APTR oldexcept;
36 #endif
38 DB2(bug("%s()\n", __FUNCTION__));
40 inf = (ThreadInfo *)FindTask(NULL)->tc_UserData;
41 // trim the name
42 //inf->task->tc_Node.ln_Name[inf->oldlen];
44 // we have to set the priority here to avoid race conditions
45 SetTaskPri(inf->task, inf->attr.param.sched_priority);
47 #ifdef USE_ASYNC_CANCEL
48 // set the exception handler for async cancellation
49 oldexcept = inf->task->tc_ExceptCode;
50 #ifdef __AROS__
51 inf->task->tc_ExceptCode = &AROS_ASMSYMNAME(CancelHandler);
52 #else
53 inf->task->tc_ExceptCode = &CancelHandler;
54 #endif
55 SetExcept(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
56 #endif
58 // set a jump point for pthread_exit
59 if (!setjmp(inf->jmp))
61 // custom stack requires special handling
62 if (inf->attr.stackaddr != NULL && inf->attr.stacksize > 0)
64 struct StackSwapArgs swapargs;
65 struct StackSwapStruct stack;
67 swapargs.Args[0] = (IPTR)inf->arg;
68 stack.stk_Lower = inf->attr.stackaddr;
69 stack.stk_Upper = (APTR)((IPTR)stack.stk_Lower + inf->attr.stacksize);
70 stack.stk_Pointer = stack.stk_Upper;
72 inf->ret = (void *)NewStackSwap(&stack, inf->start, &swapargs);
74 else
76 inf->ret = inf->start(inf->arg);
80 #ifdef USE_ASYNC_CANCEL
81 // remove the exception handler
82 SetExcept(0, SIGBREAKF_CTRL_C);
83 inf->task->tc_ExceptCode = oldexcept;
84 #endif
86 // destroy all non-NULL TLS key values
87 // since the destructors can set the keys themselves, we have to do multiple iterations
88 ObtainSemaphoreShared(&tls_sem);
89 for (j = 0; foundkey && j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
91 foundkey = FALSE;
92 for (i = 0; i < PTHREAD_KEYS_MAX; i++)
94 if (tlskeys[i].used && tlskeys[i].destructor && inf->tlsvalues[i])
96 void *oldvalue = inf->tlsvalues[i];
97 inf->tlsvalues[i] = NULL;
98 tlskeys[i].destructor(oldvalue);
99 foundkey = TRUE;
103 ReleaseSemaphore(&tls_sem);
105 if (!inf->detached)
107 // tell the parent thread that we are done
108 Forbid();
109 inf->finished = TRUE;
110 Signal(inf->parent, SIGF_PARENT);
112 else
114 // no one is waiting for us, do the clean up
115 ObtainSemaphore(&thread_sem);
116 memset(inf, 0, sizeof(ThreadInfo));
117 ReleaseSemaphore(&thread_sem);
121 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start)(void *), void *arg)
123 ThreadInfo *inf;
124 char name[NAMELEN];
125 size_t oldlen;
126 pthread_t threadnew;
128 D(bug("%s(%p, %p, %p, %p)\n", __FUNCTION__, thread, attr, start, arg));
130 if (thread == NULL || start == NULL)
131 return EINVAL;
133 ObtainSemaphore(&thread_sem);
135 // grab an empty thread slot
136 threadnew = GetThreadId(NULL);
137 if (threadnew == PTHREAD_THREADS_MAX)
139 ReleaseSemaphore(&thread_sem);
140 return EAGAIN;
143 // prepare the ThreadInfo structure
144 inf = GetThreadInfo(threadnew);
145 memset(inf, 0, sizeof(ThreadInfo));
146 inf->start = start;
147 inf->arg = arg;
148 inf->parent = FindTask(NULL);
149 if (attr)
150 inf->attr = *attr;
151 else
152 pthread_attr_init(&inf->attr);
153 NEWLIST((struct List *)&inf->cleanup);
154 inf->cancelstate = PTHREAD_CANCEL_ENABLE;
155 inf->canceltype = PTHREAD_CANCEL_DEFERRED;
157 // let's trick CreateNewProc into allocating a larger buffer for the name
158 snprintf(name, sizeof(name), "pthread thread #%d", threadnew);
159 oldlen = strlen(name);
160 memset(name + oldlen, ' ', sizeof(name) - oldlen - 1);
161 name[sizeof(name) - 1] = '\0';
163 // start the child thread
164 inf->task = (struct Task *)CreateNewProcTags(NP_Entry, StarterFunc,
165 #ifdef __MORPHOS__
166 NP_CodeType, CODETYPE_PPC,
167 (inf->attr.stackaddr == NULL && inf->attr.stacksize > 0) ? NP_PPCStackSize : TAG_IGNORE, inf->attr.stacksize,
168 #else
169 (inf->attr.stackaddr == NULL && inf->attr.stacksize > 0) ? NP_StackSize : TAG_IGNORE, inf->attr.stacksize,
170 #endif
171 NP_UserData, inf,
172 NP_Name, name,
173 TAG_DONE);
175 if (!inf->task)
177 inf->parent = NULL;
178 ReleaseSemaphore(&thread_sem);
179 return EAGAIN;
182 ReleaseSemaphore(&thread_sem);
184 *thread = threadnew;
186 return 0;