blob: 76fba0d551930242964a4ccfa4a82b4c2fd3c8a6 [file] [log] [blame]
Sharvil Nanavatia3164c92014-06-23 12:07:05 -07001/******************************************************************************
2 *
3 * Copyright (C) 2014 Google, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
Chris Mantonf8027002015-03-12 09:22:48 -070019#define LOG_TAG "bt_osi_semaphore"
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070020
21#include <assert.h>
22#include <errno.h>
Sharvil Nanavatia3164c92014-06-23 12:07:05 -070023#include <fcntl.h>
Elliott Hughesb9164f42015-01-28 15:31:26 -080024#include <malloc.h>
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070025#include <string.h>
26#include <sys/eventfd.h>
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070027
Sharvil Nanavati0f9b91e2015-03-12 15:42:50 -070028#include "osi/include/allocator.h"
29#include "osi/include/osi.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080030#include "osi/include/log.h"
Sharvil Nanavati0f9b91e2015-03-12 15:42:50 -070031#include "osi/include/semaphore.h"
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070032
33#if !defined(EFD_SEMAPHORE)
34# define EFD_SEMAPHORE (1 << 0)
35#endif
36
37struct semaphore_t {
38 int fd;
39};
40
41semaphore_t *semaphore_new(unsigned int value) {
Zach Johnson384f8a92014-08-25 23:22:24 -070042 semaphore_t *ret = osi_malloc(sizeof(semaphore_t));
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070043 if (ret) {
44 ret->fd = eventfd(value, EFD_SEMAPHORE);
Sharvil Nanavati2cb29982014-08-01 17:00:12 -070045 if (ret->fd == INVALID_FD) {
Sharvil Nanavati44802762014-12-23 23:08:58 -080046 LOG_ERROR("%s unable to allocate semaphore: %s", __func__, strerror(errno));
Sharvil Nanavatic0745da2014-11-13 01:04:19 -080047 osi_free(ret);
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070048 ret = NULL;
49 }
50 }
51 return ret;
52}
53
54void semaphore_free(semaphore_t *semaphore) {
Zach Johnson207fa232014-09-18 17:29:54 -070055 if (!semaphore)
56 return;
57
Sharvil Nanavati2cb29982014-08-01 17:00:12 -070058 if (semaphore->fd != INVALID_FD)
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070059 close(semaphore->fd);
Zach Johnson384f8a92014-08-25 23:22:24 -070060 osi_free(semaphore);
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070061}
62
63void semaphore_wait(semaphore_t *semaphore) {
64 assert(semaphore != NULL);
Sharvil Nanavati2cb29982014-08-01 17:00:12 -070065 assert(semaphore->fd != INVALID_FD);
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070066
67 uint64_t value;
68 if (eventfd_read(semaphore->fd, &value) == -1)
Sharvil Nanavati44802762014-12-23 23:08:58 -080069 LOG_ERROR("%s unable to wait on semaphore: %s", __func__, strerror(errno));
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070070}
71
Sharvil Nanavatia3164c92014-06-23 12:07:05 -070072bool semaphore_try_wait(semaphore_t *semaphore) {
73 assert(semaphore != NULL);
Sharvil Nanavati2cb29982014-08-01 17:00:12 -070074 assert(semaphore->fd != INVALID_FD);
Sharvil Nanavatia3164c92014-06-23 12:07:05 -070075
Sharvil Nanavatiae973d52016-06-20 19:16:12 -070076 int flags = TEMP_FAILURE_RETRY(fcntl(semaphore->fd, F_GETFL));
Sharvil Nanavatia3164c92014-06-23 12:07:05 -070077 if (flags == -1) {
Sharvil Nanavati44802762014-12-23 23:08:58 -080078 LOG_ERROR("%s unable to get flags for semaphore fd: %s", __func__, strerror(errno));
Sharvil Nanavatia3164c92014-06-23 12:07:05 -070079 return false;
80 }
Sharvil Nanavatiae973d52016-06-20 19:16:12 -070081 if (TEMP_FAILURE_RETRY(fcntl(semaphore->fd, F_SETFL, flags | O_NONBLOCK)) == -1) {
Sharvil Nanavati44802762014-12-23 23:08:58 -080082 LOG_ERROR("%s unable to set O_NONBLOCK for semaphore fd: %s", __func__, strerror(errno));
Sharvil Nanavatia3164c92014-06-23 12:07:05 -070083 return false;
84 }
85
86 eventfd_t value;
87 if (eventfd_read(semaphore->fd, &value) == -1)
88 return false;
89
Sharvil Nanavatiae973d52016-06-20 19:16:12 -070090 if (TEMP_FAILURE_RETRY(fcntl(semaphore->fd, F_SETFL, flags)) == -1)
Sharvil Nanavati44802762014-12-23 23:08:58 -080091 LOG_ERROR("%s unable to resetore flags for semaphore fd: %s", __func__, strerror(errno));
Sharvil Nanavatia3164c92014-06-23 12:07:05 -070092 return true;
93}
94
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070095void semaphore_post(semaphore_t *semaphore) {
96 assert(semaphore != NULL);
Sharvil Nanavati2cb29982014-08-01 17:00:12 -070097 assert(semaphore->fd != INVALID_FD);
Sharvil Nanavatic11b4072014-05-02 23:55:09 -070098
99 if (eventfd_write(semaphore->fd, 1ULL) == -1)
Sharvil Nanavati44802762014-12-23 23:08:58 -0800100 LOG_ERROR("%s unable to post to semaphore: %s", __func__, strerror(errno));
Sharvil Nanavatic11b4072014-05-02 23:55:09 -0700101}
Sharvil Nanavatif4013f22014-07-05 20:42:07 -0700102
103int semaphore_get_fd(const semaphore_t *semaphore) {
104 assert(semaphore != NULL);
Sharvil Nanavati2cb29982014-08-01 17:00:12 -0700105 assert(semaphore->fd != INVALID_FD);
Sharvil Nanavatif4013f22014-07-05 20:42:07 -0700106 return semaphore->fd;
107}