1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled/precompiled.hpp" 26 #include "semaphore_bsd.hpp" 27 #include "utilities/debug.hpp" 28 29 #include <semaphore.h> 30 31 #ifdef __APPLE__ 32 // OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used. 33 34 static const char* sem_init_strerror(kern_return_t value) { 35 switch (value) { 36 case KERN_INVALID_ARGUMENT: return "Invalid argument"; 37 case KERN_RESOURCE_SHORTAGE: return "Resource shortage"; 38 default: return "Unknown"; 39 } 40 } 41 42 OSXSemaphore::OSXSemaphore(uint value) { 43 kern_return_t ret = semaphore_create(mach_task_self(), &_semaphore, SYNC_POLICY_FIFO, value); 44 45 guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret)); 46 } 47 48 OSXSemaphore::~OSXSemaphore() { 49 semaphore_destroy(mach_task_self(), _semaphore); 50 } 51 52 void OSXSemaphore::signal(uint count) { 53 for (uint i = 0; i < count; i++) { 54 kern_return_t ret = semaphore_signal(_semaphore); 55 56 assert(ret == KERN_SUCCESS, "Failed to signal semaphore"); 57 } 58 } 59 60 void OSXSemaphore::wait() { 61 kern_return_t ret; 62 while ((ret = semaphore_wait(_semaphore)) == KERN_ABORTED) { 63 // Semaphore was interrupted. Retry. 64 } 65 assert(ret == KERN_SUCCESS, "Failed to wait on semaphore"); 66 } 67 68 int64_t OSXSemaphore::currenttime() { 69 struct timeval tv; 70 gettimeofday(&tv, NULL); 71 return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); 72 } 73 74 bool OSXSemaphore::trywait() { 75 return timedwait(0, 0); 76 } 77 78 bool OSXSemaphore::timedwait(unsigned int sec, int nsec) { 79 kern_return_t kr = KERN_ABORTED; 80 mach_timespec_t waitspec; 81 waitspec.tv_sec = sec; 82 waitspec.tv_nsec = nsec; 83 84 int64_t starttime = currenttime(); 85 86 kr = semaphore_timedwait(_semaphore, waitspec); 87 while (kr == KERN_ABORTED) { 88 int64_t totalwait = (sec * NANOSECS_PER_SEC) + nsec; 89 90 int64_t current = currenttime(); 91 int64_t passedtime = current - starttime; 92 93 if (passedtime >= totalwait) { 94 waitspec.tv_sec = 0; 95 waitspec.tv_nsec = 0; 96 } else { 97 int64_t waittime = totalwait - (current - starttime); 98 waitspec.tv_sec = waittime / NANOSECS_PER_SEC; 99 waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; 100 } 101 102 kr = semaphore_timedwait(_semaphore, waitspec); 103 } 104 105 return kr == KERN_SUCCESS; 106 } 107 #endif // __APPLE__