1/* 2 * Copyright (c) 2005-2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#include <stdio.h> 24#include <stdlib.h> 25#include <mach-o/dyld.h> 26#include <pthread.h> 27#include <unistd.h> 28#include <Availability.h> 29 30#include "test.h" 31 32/// rdar://problem/3811777 33 34// barrier thread 1 thread 2 35// add image 36// 1 37// acquire sMyLock 38// 2 39// in callback acquire sMyLock call lazy pointer 40// release sMyLock release sMyLock 41 42extern void foo(); 43 44#if __MAC_OS_X_VERSION_MIN_REQUIRED 45 46static volatile int sBarrier = 0; 47static pthread_mutex_t sBarrierMutex; 48static pthread_cond_t sBarrierFree; 49 50static void blockUntilBarrier(int n) 51{ 52 pthread_mutex_lock(&sBarrierMutex); 53 while ( sBarrier < n ) 54 pthread_cond_wait(&sBarrierFree, &sBarrierMutex); 55 pthread_mutex_unlock(&sBarrierMutex); 56} 57 58static void advanceToBarrier(int n) 59{ 60 pthread_mutex_lock(&sBarrierMutex); 61 sBarrier = n; 62 pthread_cond_broadcast(&sBarrierFree); 63 pthread_mutex_unlock(&sBarrierMutex); 64} 65 66 67 68 69 70static pthread_mutex_t sMyLock; 71 72static void* thread2(void* arg) 73{ 74 // thread 2 75 blockUntilBarrier(1); 76 pthread_mutex_lock(&sMyLock); 77 advanceToBarrier(2); 78 foo(); 79 pthread_mutex_unlock(&sMyLock); 80 return NULL; 81} 82 83 84 85static void myImageHandler(const struct mach_header *mh, intptr_t vmaddr_slide) 86{ 87 // thread 1 88 if ( NSLookupSymbolInImage(mh, "_bar", 0) != NULL ) { 89 advanceToBarrier(1); 90 blockUntilBarrier(2); 91 pthread_mutex_lock(&sMyLock); 92 pthread_mutex_unlock(&sMyLock); 93 } 94} 95#endif 96 97int main() 98{ 99#if __MAC_OS_X_VERSION_MIN_REQUIRED 100 pthread_mutex_init(&sBarrierMutex, NULL); 101 pthread_cond_init(&sBarrierFree, NULL); 102 pthread_mutex_init(&sMyLock, NULL); 103 104 // self-terminate this process if it locks up for two seconds 105 alarm(2); 106 107 advanceToBarrier(0); 108 109 pthread_t pthread2; 110 if ( pthread_create(&pthread2, NULL, thread2, NULL) != 0 ) { 111 FAIL("pthread_create failed"); 112 exit(0); 113 } 114 115 // thread 1 116 _dyld_register_func_for_add_image(&myImageHandler); 117 NSAddImage("bar.dylib", 0); 118#endif 119 120 PASS("deadlock"); 121 return 0; 122} 123