1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * Copyright (c) 2008 Likewise Software, Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Portions of this software have been released under the following terms: 32 * 33 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 34 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 35 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 36 * 37 * To anyone who acknowledges that this file is provided "AS IS" 38 * without any express or implied warranty: 39 * permission to use, copy, modify, and distribute this file for any 40 * purpose is hereby granted without fee, provided that the above 41 * copyright notices and this notice appears in all source code copies, 42 * and that none of the names of Open Software Foundation, Inc., Hewlett- 43 * Packard Company or Digital Equipment Corporation be used 44 * in advertising or publicity pertaining to distribution of the software 45 * without specific, written prior permission. Neither Open Software 46 * Foundation, Inc., Hewlett-Packard Company nor Digital 47 * Equipment Corporation makes any representations about the suitability 48 * of this software for any purpose. 49 * 50 * Copyright (c) 2007, Novell, Inc. All rights reserved. 51 * Redistribution and use in source and binary forms, with or without 52 * modification, are permitted provided that the following conditions 53 * are met: 54 * 55 * 1. Redistributions of source code must retain the above copyright 56 * notice, this list of conditions and the following disclaimer. 57 * 2. Redistributions in binary form must reproduce the above copyright 58 * notice, this list of conditions and the following disclaimer in the 59 * documentation and/or other materials provided with the distribution. 60 * 3. Neither the name of Novell Inc. nor the names of its contributors 61 * may be used to endorse or promote products derived from this 62 * this software without specific prior written permission. 63 * 64 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 65 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 66 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 67 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 68 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 69 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 70 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 71 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 72 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 73 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 74 * 75 * @APPLE_LICENSE_HEADER_END@ 76 */ 77 78#include <config.h> 79#include <errno.h> 80 81#include "dcethread-private.h" 82#include "dcethread-util.h" 83#include "dcethread-debug.h" 84 85#ifdef API 86 87typedef struct 88{ 89 void* (*start) (void* data); 90 void* data; 91 dcethread* self; 92} dcethread_start_args; 93 94static void * 95proxy_start(void *arg) 96{ 97 dcethread_start_args *args = (dcethread_start_args*) arg; 98 void *result; 99 int prev_cancel_state; 100 int prev_cancel_type; 101 102 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &prev_cancel_state); 103 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &prev_cancel_type); 104 dcethread__init_self(args->self); 105 106 result = args->start(args->data); 107 108 (void) pthread_setcancelstate(prev_cancel_state, NULL); 109 (void) pthread_setcanceltype(prev_cancel_type, NULL); 110 111 dcethread__lock(args->self); 112 args->self->status = result; 113 dcethread__cleanup_self(args->self); 114 dcethread__unlock(args->self); 115 116 free(args); 117 118 return result; 119} 120 121int 122dcethread_create(dcethread** _thread, dcethread_attr* attr, void *(*start_routine)(void *), void *arg) 123{ 124 dcethread_start_args *start_args; 125 dcethread* thread; 126 int detachstate; 127 128 start_args = (dcethread_start_args *) malloc(sizeof(*start_args)); 129 if (start_args == NULL) 130 { 131 return dcethread__set_errno(ENOMEM); 132 } 133 134 start_args->start = start_routine; 135 start_args->data = arg; 136 start_args->self = thread = dcethread__new(); 137 138 /* Record if this thread was created joinably */ 139 if (!attr || (pthread_attr_getdetachstate(attr, &detachstate), detachstate == PTHREAD_CREATE_JOINABLE)) 140 { 141 thread->flag.joinable = 1; 142 } 143 144 /* If thread is joinable, give it an extra reference */ 145 if (thread->flag.joinable) 146 { 147 thread->refs++; 148 } 149 150 if (dcethread__set_errno(pthread_create((pthread_t*) &thread->pthread, attr, proxy_start, start_args))) 151 { 152 dcethread__delete(thread); 153 free(start_args); 154 return -1; 155 } 156 157 DCETHREAD_TRACE("Thread %p: created (pthread %lu)", thread, (unsigned long) thread->pthread); 158 159 dcethread__lock(thread); 160 while (thread->state == DCETHREAD_STATE_CREATED) 161 { 162 dcethread__wait(thread); 163 } 164 dcethread__unlock(thread); 165 166 DCETHREAD_TRACE("Thread %p: started", thread); 167 168 *_thread = thread; 169 return dcethread__set_errno(0); 170} 171 172int 173dcethread_create_throw(dcethread** _thread, dcethread_attr* attr, void *(*start_routine)(void *), void *arg) 174{ 175 DCETHREAD_WRAP_THROW(dcethread_create(_thread, attr, start_routine, arg)); 176} 177 178#endif /* API */ 179 180#ifdef TEST 181 182#include "dcethread-test.h" 183 184static void* volatile basic_result = 0; 185 186static void* 187basic(void* data) 188{ 189 basic_result = data; 190 191 return data; 192} 193 194MU_TEST(dcethread_create, basic) 195{ 196 dcethread* thread = NULL; 197 198 MU_TRY_DCETHREAD( dcethread_create(&thread, NULL, basic, (void*) 0xDEADBEEF) ); 199 200 MU_ASSERT(thread != NULL); 201 202 while (basic_result != (void*) 0xDEADBEEF) 203 { 204 dcethread_yield(); 205 } 206} 207 208#endif /* TEST */ 209