Commit 4d119477 authored by Orvid King's avatar Orvid King Committed by Facebook Github Bot

Implement the basic operations on sem_t

Summary: This means that Windows builds no longer require pthreads in order to run tests. (previously we were relying on the pthreads implementation we were using to provide semaphore.h for us)

Reviewed By: yfeldblum

Differential Revision: D9568125

fbshipit-source-id: 712f542c9a29627f72b41e1def2b79d591a33317
parent c3e09627
/*
* Copyright 2012-present Facebook, Inc.
*
* 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.
*/
#include <folly/portability/Semaphore.h>
#include <folly/portability/Windows.h>
#include <errno.h>
#include <mutex>
#if _WIN32
namespace folly::portability::semaphore {
struct sem_t_ {
std::mutex mtx{};
HANDLE sema{INVALID_HANDLE_VALUE};
int32_t value{0};
};
int sem_init(sem_t* s, int shared, unsigned int value) {
// Don't support cross-process shared semaphores.
if (shared != 0) {
return -1;
}
auto sem = CreateSemaphoreA(nullptr, 0, SEM_VALUE_MAX, nullptr);
if (sem == 0) {
return -1;
}
auto ret = new sem_t_();
ret->sema = sem;
ret->value = value;
*s = ret;
return 0;
}
int sem_destroy(sem_t* s) {
if (!CloseHandle((*s)->sema)) {
return -1;
}
delete *s;
*s = nullptr;
return 0;
}
int sem_post(sem_t* s) {
std::lock_guard<std::mutex> lock{(*s)->mtx};
if ((*s)->value < SEM_VALUE_MAX) {
if (++(*s)->value <= 0 && !ReleaseSemaphore((*s)->sema, 1, nullptr)) {
--(*s)->value;
errno = EINVAL;
return -1;
}
} else {
errno = ERANGE;
return -1;
}
return 0;
}
int sem_trywait(sem_t* s) {
std::lock_guard<std::mutex> lock{(*s)->mtx};
if ((*s)->value > 0) {
(*s)->value--;
return 0;
} else {
errno = EAGAIN;
return -1;
}
}
int sem_wait(sem_t* s) {
int32_t value = 0;
{
std::lock_guard<std::mutex> lock{(*s)->mtx};
value = --(*s)->value;
}
if (value < 0) {
if (WaitForSingleObject((*s)->sema, INFINITE) != WAIT_OBJECT_0) {
errno = EINVAL;
return -1;
}
}
return 0;
}
} // namespace folly::portability::semaphore
#endif
......@@ -16,9 +16,20 @@
#pragma once
// On Windows, the include order matters, as the pthread implementation we
// support attempts to use a different definition of `mode_t` than everything
// else, so we have to make sure our definition of it is first.
#include <folly/portability/SysTypes.h>
#ifndef _WIN32
#include <semaphore.h>
#else
#include <limits.h>
#define SEM_VALUE_MAX INT_MAX
namespace folly::portability::semaphore {
using sem_t = struct sem_t_*;
int sem_init(sem_t* s, int shared, unsigned int value);
int sem_destroy(sem_t* s);
int sem_post(sem_t* s);
int sem_trywait(sem_t* s);
int sem_wait(sem_t* s);
} // namespace folly::portability::semaphore
/* using override */ using namespace folly::portability::semaphore;
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment