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>
26 #include "pthread_intern.h"
29 static void StarterFunc(void)
34 #ifdef USE_ASYNC_CANCEL
38 DB2(bug("%s()\n", __FUNCTION__
));
40 inf
= (ThreadInfo
*)FindTask(NULL
)->tc_UserData
;
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
;
51 inf
->task
->tc_ExceptCode
= &AROS_ASMSYMNAME(CancelHandler
);
53 inf
->task
->tc_ExceptCode
= &CancelHandler
;
55 SetExcept(SIGBREAKF_CTRL_C
, SIGBREAKF_CTRL_C
);
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
);
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
;
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
++)
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
);
103 ReleaseSemaphore(&tls_sem
);
107 // tell the parent thread that we are done
109 inf
->finished
= TRUE
;
110 Signal(inf
->parent
, SIGF_PARENT
);
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
)
128 D(bug("%s(%p, %p, %p, %p)\n", __FUNCTION__
, thread
, attr
, start
, arg
));
130 if (thread
== NULL
|| start
== NULL
)
133 ObtainSemaphore(&thread_sem
);
135 // grab an empty thread slot
136 threadnew
= GetThreadId(NULL
);
137 if (threadnew
== PTHREAD_THREADS_MAX
)
139 ReleaseSemaphore(&thread_sem
);
143 // prepare the ThreadInfo structure
144 inf
= GetThreadInfo(threadnew
);
145 memset(inf
, 0, sizeof(ThreadInfo
));
148 inf
->parent
= FindTask(NULL
);
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
,
166 NP_CodeType
, CODETYPE_PPC
,
167 (inf
->attr
.stackaddr
== NULL
&& inf
->attr
.stacksize
> 0) ? NP_PPCStackSize
: TAG_IGNORE
, inf
->attr
.stacksize
,
169 (inf
->attr
.stackaddr
== NULL
&& inf
->attr
.stacksize
> 0) ? NP_StackSize
: TAG_IGNORE
, inf
->attr
.stacksize
,
178 ReleaseSemaphore(&thread_sem
);
182 ReleaseSemaphore(&thread_sem
);