/* * %CopyrightBegin% * * Copyright Ericsson AB 1997-2017. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * %CopyrightEnd% * */ /* * common interface to some simple synchronisation primitives for * internal use by ei. */ /* Note that these locks are NOT recursive on Win32 or Solaris, * i.e. self-deadlock will occur if a thread tries to obtain a lock it * is already holding. */ #include "eidef.h" #ifdef __WIN32__ #include #include #include #else /* unix */ #include #include #include #endif /* platforms */ #include "ei_malloc.h" #include "ei_locking.h" #ifdef _REENTRANT /* * Create a new mutex object. * Returns a pointer to the mutex if successful, NULL otherwise. */ ei_mutex_t *ei_mutex_create(void) { ei_mutex_t *l; if ((l = ei_malloc(sizeof(*l))) == NULL) return NULL; #ifdef __WIN32__ l->lock = CreateMutex(NULL,FALSE,NULL); #else /* unix */ l->lock = ei_m_create(); #endif return l; } /* * Free a mutex and the structure associated with it. * * This function attempts to obtain the mutex before releasing it; * If nblock == 1 and the mutex was unavailable, the function will * return failure and the mutex will not have been removed. * * If nblock == 0 the function will block until the mutex becomes * available, at which time it will be removed and the function will * succeed. * * returns 0 if the mutex is removed, -1 on failure (busy) */ int ei_mutex_free(ei_mutex_t *l, int nblock) { /* attempt to lock it first, to make sure it's really free */ if (ei_mutex_lock(l,nblock)) return -1; /* attempt failed */ /* we are now holding the lock */ #ifdef __WIN32__ CloseHandle(l->lock); #else /* unix */ ei_m_destroy(l->lock); #endif ei_free(l); return 0; } /* Grab a mutex. If the mutex is not held by any other process the * function returns so that the caller may enter a critical section. * Processes subsequently wishing to obtain the lock will block * until this process releases it. * * If the mutex is busy (held by some other process) and nblock == 0, * the function will block until the mutex is freed by the process * holding it, returning only when the mutex has been grabbed. * * If the mutex is busy and nblock != 0, the function will not block. * Instead it will return -1 immediately, indicating that the * operation failed. * Returns 0 on success, -1 on failure. */ int ei_mutex_lock(ei_mutex_t *l, int nblock) { #ifdef __WIN32__ /* check valid values for timeout: is 0 ok? */ if (WaitForSingleObject(l->lock,(nblock? 0 : INFINITE)) != WAIT_OBJECT_0) return -1; #else /* unix */ if (nblock) { if (ei_m_trylock(l->lock) < 0) return -1; } else ei_m_lock(l->lock); #endif return 0; } /* Release a mutex */ int ei_mutex_unlock(ei_mutex_t *l) { #ifdef __WIN32__ ReleaseMutex(l->lock); #else /* unix */ ei_m_unlock(l->lock); #endif return 0; } #endif /* _REENTRANT */