mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-11-12 14:57:20 +00:00
[common/client] platform: add portable worker primitives
This commit is contained in:
@@ -26,18 +26,17 @@
|
||||
#include "common/debug.h"
|
||||
#include "common/event.h"
|
||||
#include "common/locking.h"
|
||||
#include "common/semaphore.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/util.h"
|
||||
#include "common/ringbuffer.h"
|
||||
|
||||
#include "dynamic/audiodev.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <samplerate.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdalign.h>
|
||||
#include <stdatomic.h>
|
||||
#include <string.h>
|
||||
@@ -303,16 +302,16 @@ typedef struct
|
||||
LG_Lock deviceLock;
|
||||
struct
|
||||
{
|
||||
sem_t wake;
|
||||
bool wakeInitialized;
|
||||
atomic_bool wakePending;
|
||||
LGThread * thread;
|
||||
atomic_bool stop;
|
||||
LGSemaphore * wake;
|
||||
bool wakeInitialized;
|
||||
atomic_bool wakePending;
|
||||
LGThread * thread;
|
||||
atomic_bool stop;
|
||||
}
|
||||
worker;
|
||||
_Atomic(StreamState) state;
|
||||
atomic_uint callbackState;
|
||||
sem_t callbackIdle;
|
||||
LGSemaphore * callbackIdle;
|
||||
bool callbackIdleInitialized;
|
||||
atomic_uint streamGeneration;
|
||||
uint64_t requestSerial;
|
||||
@@ -410,13 +409,13 @@ typedef struct
|
||||
|
||||
struct
|
||||
{
|
||||
LG_Lock lock;
|
||||
sem_t wake;
|
||||
bool wakeInitialized;
|
||||
atomic_bool wakePending;
|
||||
LGThread * thread;
|
||||
atomic_bool stop;
|
||||
bool pending;
|
||||
LG_Lock lock;
|
||||
LGSemaphore * wake;
|
||||
bool wakeInitialized;
|
||||
atomic_bool wakePending;
|
||||
LGThread * thread;
|
||||
atomic_bool stop;
|
||||
bool pending;
|
||||
|
||||
const LG_AudioOps * ops;
|
||||
void * opaque;
|
||||
@@ -1087,7 +1086,7 @@ static void playbackCallbackExit(void)
|
||||
if ((previous & PLAYBACK_CALLBACK_DISABLED) &&
|
||||
(previous & PLAYBACK_CALLBACK_COUNT_MASK) == 1 &&
|
||||
audio.playback.callbackIdleInitialized)
|
||||
sem_post(&audio.playback.callbackIdle);
|
||||
lgSignalSemaphore(audio.playback.callbackIdle);
|
||||
}
|
||||
|
||||
static void playbackDisableCallbacks(void)
|
||||
@@ -1103,12 +1102,7 @@ static void playbackWaitForCallbacks(void)
|
||||
&audio.playback.callbackState, memory_order_acquire) &
|
||||
PLAYBACK_CALLBACK_COUNT_MASK) != 0)
|
||||
{
|
||||
int result;
|
||||
do
|
||||
result = sem_wait(&audio.playback.callbackIdle);
|
||||
while (result < 0 && errno == EINTR);
|
||||
|
||||
if (result < 0)
|
||||
if (!lgWaitSemaphore(audio.playback.callbackIdle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1121,7 +1115,7 @@ static void playbackWorkerWake(void)
|
||||
&audio.playback.worker.wakePending, true, memory_order_acq_rel))
|
||||
return;
|
||||
|
||||
if (sem_post(&audio.playback.worker.wake) < 0 && errno != EOVERFLOW)
|
||||
if (!lgSignalSemaphore(audio.playback.worker.wake))
|
||||
atomic_store_explicit(
|
||||
&audio.playback.worker.wakePending, false, memory_order_release);
|
||||
}
|
||||
@@ -1133,7 +1127,7 @@ static void feedbackWorkerWake(void)
|
||||
&audio.feedback.wakePending, true, memory_order_acq_rel))
|
||||
return;
|
||||
|
||||
if (sem_post(&audio.feedback.wake) < 0 && errno != EOVERFLOW)
|
||||
if (!lgSignalSemaphore(audio.feedback.wake))
|
||||
atomic_store_explicit(
|
||||
&audio.feedback.wakePending, false, memory_order_release);
|
||||
}
|
||||
@@ -4395,11 +4389,7 @@ static int playbackThread(void * opaque)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
int result;
|
||||
do
|
||||
result = sem_wait(&audio.playback.worker.wake);
|
||||
while (result < 0 && errno == EINTR);
|
||||
if (result < 0)
|
||||
if (!lgWaitSemaphore(audio.playback.worker.wake))
|
||||
break;
|
||||
|
||||
atomic_store_explicit(
|
||||
@@ -4453,11 +4443,7 @@ static int feedbackThread(void * opaque)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int result;
|
||||
do
|
||||
result = sem_wait(&audio.feedback.wake);
|
||||
while (result < 0 && errno == EINTR);
|
||||
if (result < 0)
|
||||
if (!lgWaitSemaphore(audio.feedback.wake))
|
||||
break;
|
||||
|
||||
atomic_store_explicit(
|
||||
@@ -4577,7 +4563,8 @@ void lgAudio_init(void)
|
||||
&audio.playback.callbackState, PLAYBACK_CALLBACK_DISABLED,
|
||||
memory_order_release);
|
||||
|
||||
if (sem_init(&audio.playback.callbackIdle, 0, 0) != 0)
|
||||
audio.playback.callbackIdle = lgCreateSemaphore(0);
|
||||
if (!audio.playback.callbackIdle)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the audio callback semaphore");
|
||||
return;
|
||||
@@ -4591,7 +4578,8 @@ void lgAudio_init(void)
|
||||
goto err_callback;
|
||||
}
|
||||
|
||||
if (sem_init(&audio.playback.worker.wake, 0, 0) != 0)
|
||||
audio.playback.worker.wake = lgCreateSemaphore(0);
|
||||
if (!audio.playback.worker.wake)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the audio playback semaphore");
|
||||
goto err_active;
|
||||
@@ -4604,7 +4592,8 @@ void lgAudio_init(void)
|
||||
goto err_playbackWake;
|
||||
}
|
||||
|
||||
if (sem_init(&audio.feedback.wake, 0, 0) != 0)
|
||||
audio.feedback.wake = lgCreateSemaphore(0);
|
||||
if (!audio.feedback.wake)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create the audio feedback semaphore");
|
||||
goto err_playbackThread;
|
||||
@@ -4648,7 +4637,8 @@ void lgAudio_init(void)
|
||||
return;
|
||||
|
||||
err_feedbackWake:
|
||||
sem_destroy(&audio.feedback.wake);
|
||||
lgFreeSemaphore(audio.feedback.wake);
|
||||
audio.feedback.wake = NULL;
|
||||
audio.feedback.wakeInitialized = false;
|
||||
|
||||
err_playbackThread:
|
||||
@@ -4659,7 +4649,8 @@ err_playbackThread:
|
||||
audio.playback.worker.thread = NULL;
|
||||
|
||||
err_playbackWake:
|
||||
sem_destroy(&audio.playback.worker.wake);
|
||||
lgFreeSemaphore(audio.playback.worker.wake);
|
||||
audio.playback.worker.wake = NULL;
|
||||
audio.playback.worker.wakeInitialized = false;
|
||||
|
||||
err_active:
|
||||
@@ -4667,7 +4658,8 @@ err_active:
|
||||
audio.activeIdle = NULL;
|
||||
|
||||
err_callback:
|
||||
sem_destroy(&audio.playback.callbackIdle);
|
||||
lgFreeSemaphore(audio.playback.callbackIdle);
|
||||
audio.playback.callbackIdle = NULL;
|
||||
audio.playback.callbackIdleInitialized = false;
|
||||
}
|
||||
|
||||
@@ -4696,7 +4688,8 @@ void lgAudio_free(void)
|
||||
}
|
||||
if (audio.playback.worker.wakeInitialized)
|
||||
{
|
||||
sem_destroy(&audio.playback.worker.wake);
|
||||
lgFreeSemaphore(audio.playback.worker.wake);
|
||||
audio.playback.worker.wake = NULL;
|
||||
audio.playback.worker.wakeInitialized = false;
|
||||
}
|
||||
|
||||
@@ -4710,7 +4703,8 @@ void lgAudio_free(void)
|
||||
}
|
||||
if (audio.feedback.wakeInitialized)
|
||||
{
|
||||
sem_destroy(&audio.feedback.wake);
|
||||
lgFreeSemaphore(audio.feedback.wake);
|
||||
audio.feedback.wake = NULL;
|
||||
audio.feedback.wakeInitialized = false;
|
||||
}
|
||||
|
||||
@@ -4740,7 +4734,8 @@ void lgAudio_free(void)
|
||||
|
||||
if (audio.playback.callbackIdleInitialized)
|
||||
{
|
||||
sem_destroy(&audio.playback.callbackIdle);
|
||||
lgFreeSemaphore(audio.playback.callbackIdle);
|
||||
audio.playback.callbackIdle = NULL;
|
||||
audio.playback.callbackIdleInitialized = false;
|
||||
}
|
||||
if (audio.activeIdle)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "common/debug.h"
|
||||
#include "common/event.h"
|
||||
#include "common/locking.h"
|
||||
#include "common/random.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/time.h"
|
||||
|
||||
@@ -44,7 +45,6 @@
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/random.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/types.h>
|
||||
@@ -228,26 +228,6 @@ static bool filesLockInitialized;
|
||||
static atomic_bool forceLocalEof;
|
||||
#endif
|
||||
|
||||
static bool randomBytes(void * buffer, size_t size)
|
||||
{
|
||||
uint8_t * bytes = buffer;
|
||||
size_t offset = 0;
|
||||
while (offset < size)
|
||||
{
|
||||
const ssize_t result = getrandom(bytes + offset, size - offset, 0);
|
||||
if (result < 0 && errno == EINTR)
|
||||
continue;
|
||||
if (result <= 0)
|
||||
{
|
||||
if (!result)
|
||||
errno = EIO;
|
||||
return false;
|
||||
}
|
||||
offset += (size_t)result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint64_t nsFromTimespec(struct timespec value)
|
||||
{
|
||||
if (value.tv_sec < 0 || value.tv_nsec < 0)
|
||||
@@ -3446,7 +3426,7 @@ bool clipboardFiles_init(void)
|
||||
LG_LOCK_INIT(files.lock);
|
||||
filesLockInitialized = true;
|
||||
uint64_t nonce = 0;
|
||||
if (!randomBytes(&nonce, sizeof(nonce)))
|
||||
if (!lgRandomBytes(&nonce, sizeof(nonce)))
|
||||
{
|
||||
DEBUG_ERROR("Failed to seed clipboard file transfer identifiers: %s",
|
||||
strerror(errno));
|
||||
|
||||
@@ -21,11 +21,14 @@
|
||||
#include "test.h"
|
||||
|
||||
#include "common/event.h"
|
||||
#include "common/random.h"
|
||||
#include "common/semaphore.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST_WAIT_NS UINT64_C(1000000000)
|
||||
|
||||
@@ -40,6 +43,12 @@ struct TimerState
|
||||
atomic_uint calls;
|
||||
};
|
||||
|
||||
struct SemaphoreState
|
||||
{
|
||||
LGSemaphore * semaphore;
|
||||
LGEvent * complete;
|
||||
};
|
||||
|
||||
static int signalThread(void * opaque)
|
||||
{
|
||||
const struct SignalState * state = opaque;
|
||||
@@ -60,6 +69,14 @@ static bool timerCallback(void * opaque)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int semaphoreThread(void * opaque)
|
||||
{
|
||||
const struct SemaphoreState * state = opaque;
|
||||
CHECK(lgWaitSemaphore(state->semaphore));
|
||||
CHECK(lgSignalEvent(state->complete));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void testEventWaits(void)
|
||||
{
|
||||
LGEvent * event = lgCreateEvent(true, 0);
|
||||
@@ -107,11 +124,50 @@ static void testTimer(void)
|
||||
lgFreeEvent(event);
|
||||
}
|
||||
|
||||
static void testSemaphore(void)
|
||||
{
|
||||
LGSemaphore * semaphore = lgCreateSemaphore(0);
|
||||
LGEvent * complete = lgCreateEvent(true, 0);
|
||||
CHECK(semaphore);
|
||||
CHECK(complete);
|
||||
|
||||
const struct SemaphoreState state =
|
||||
{
|
||||
.semaphore = semaphore,
|
||||
.complete = complete,
|
||||
};
|
||||
LGThread * thread;
|
||||
CHECK(lgCreateThread(
|
||||
"semaphore", semaphoreThread, (void *)&state, &thread));
|
||||
CHECK(!lgWaitEventNS(complete, UINT64_C(1000000)));
|
||||
CHECK(lgSignalSemaphore(semaphore));
|
||||
CHECK(lgWaitEventNS(complete, TEST_WAIT_NS));
|
||||
CHECK(lgJoinThread(thread, NULL));
|
||||
|
||||
CHECK(lgSignalSemaphore(semaphore));
|
||||
CHECK(lgSignalSemaphore(semaphore));
|
||||
CHECK(lgWaitSemaphore(semaphore));
|
||||
CHECK(lgWaitSemaphore(semaphore));
|
||||
lgFreeEvent(complete);
|
||||
lgFreeSemaphore(semaphore);
|
||||
}
|
||||
|
||||
static void testRandom(void)
|
||||
{
|
||||
uint8_t first [32] = { 0 };
|
||||
uint8_t second[32] = { 0 };
|
||||
CHECK(lgRandomBytes(first, sizeof(first)));
|
||||
CHECK(lgRandomBytes(second, sizeof(second)));
|
||||
CHECK(memcmp(first, second, sizeof(first)) != 0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
lgTimeInit();
|
||||
testEventWaits();
|
||||
testManualReset();
|
||||
testTimer();
|
||||
testSemaphore();
|
||||
testRandom();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,19 +23,18 @@
|
||||
#include <LGProtocol/KVMFR.h>
|
||||
#include "common/debug.h"
|
||||
#include "common/locking.h"
|
||||
#include "common/random.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#include <lgmp/stream.h>
|
||||
#include <lgmp/spmc.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
#define AUDIO_IDLE_POLL_MS 20U
|
||||
#define AUDIO_ACTIVE_POLL_US 25U
|
||||
@@ -242,22 +241,6 @@ static uint32_t nextNonzero(uint32_t * value)
|
||||
return *value;
|
||||
}
|
||||
|
||||
static bool randomBytes(void * buffer, size_t size)
|
||||
{
|
||||
uint8_t * output = buffer;
|
||||
while (size)
|
||||
{
|
||||
const ssize_t received = getrandom(output, size, 0);
|
||||
if (received < 0 && errno == EINTR)
|
||||
continue;
|
||||
if (received <= 0)
|
||||
return false;
|
||||
output += (size_t)received;
|
||||
size -= (size_t)received;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool tryControlWriteGate(LGMPAudio * audio)
|
||||
{
|
||||
return !atomic_flag_test_and_set_explicit(
|
||||
@@ -2512,7 +2495,7 @@ bool lgmpAudio_create(PLGMPClient client, LGEvent * pointerWake,
|
||||
return false;
|
||||
}
|
||||
audio->generationSerial = 1;
|
||||
if (!randomBytes(&audio->requestSerial,
|
||||
if (!lgRandomBytes(&audio->requestSerial,
|
||||
sizeof(audio->requestSerial)))
|
||||
{
|
||||
lgFreeEvent(audio->event);
|
||||
@@ -2668,7 +2651,7 @@ void lgmpAudio_disconnect(LGMPAudio * audio)
|
||||
static bool newClaimNL(LGMPAudio * audio)
|
||||
{
|
||||
uint64_t token = 0;
|
||||
if (!randomBytes(&token, sizeof(token)))
|
||||
if (!lgRandomBytes(&token, sizeof(token)))
|
||||
{
|
||||
token = microtime() ^ ((uint64_t)audio->clientID << 32) ^
|
||||
audio->requestSerial;
|
||||
|
||||
@@ -25,17 +25,16 @@
|
||||
#include "common/debug.h"
|
||||
#include "common/event.h"
|
||||
#include "common/locking.h"
|
||||
#include "common/random.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/time.h"
|
||||
|
||||
#include <lgmp/stream.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
#define CLIPBOARD_PENDING_MAX 128U
|
||||
#define CLIPBOARD_PENDING_NORMAL_MAX 64U
|
||||
@@ -366,26 +365,6 @@ static uint64_t nextClientGeneration(LGMPClipboard * clipboard)
|
||||
return clipboard->localGenerationSerial;
|
||||
}
|
||||
|
||||
static bool randomBytes(void * buffer, size_t size)
|
||||
{
|
||||
uint8_t * output = buffer;
|
||||
while (size)
|
||||
{
|
||||
const ssize_t received = getrandom(output, size, 0);
|
||||
if (received < 0 && errno == EINTR)
|
||||
continue;
|
||||
if (received <= 0)
|
||||
{
|
||||
if (!received)
|
||||
errno = EIO;
|
||||
return false;
|
||||
}
|
||||
output += (size_t)received;
|
||||
size -= (size_t)received;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static LG_ClipboardFileError fromWireFileError(uint32_t error)
|
||||
{
|
||||
switch (error)
|
||||
@@ -2365,7 +2344,7 @@ bool lgmpClipboard_create(PLGMPClient client, LGMPClipboard ** result)
|
||||
return false;
|
||||
clipboard->client = client;
|
||||
uint64_t nonce = 0;
|
||||
if (!randomBytes(&nonce, sizeof(nonce)))
|
||||
if (!lgRandomBytes(&nonce, sizeof(nonce)))
|
||||
{
|
||||
free(clipboard);
|
||||
return false;
|
||||
|
||||
29
common/include/common/random.h
Normal file
29
common/include/common/random.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_LG_COMMON_RANDOM_
|
||||
#define _H_LG_COMMON_RANDOM_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
bool lgRandomBytes(void * buffer, size_t size);
|
||||
|
||||
#endif
|
||||
33
common/include/common/semaphore.h
Normal file
33
common/include/common/semaphore.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _H_LG_COMMON_SEMAPHORE_
|
||||
#define _H_LG_COMMON_SEMAPHORE_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct LGSemaphore LGSemaphore;
|
||||
|
||||
LGSemaphore * lgCreateSemaphore(unsigned int initialValue);
|
||||
void lgFreeSemaphore (LGSemaphore * semaphore);
|
||||
bool lgWaitSemaphore (LGSemaphore * semaphore);
|
||||
bool lgSignalSemaphore(LGSemaphore * semaphore);
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,8 @@ add_library(lg_common_platform_code STATIC
|
||||
sysinfo.c
|
||||
thread.c
|
||||
event.c
|
||||
semaphore.c
|
||||
random.c
|
||||
ivshmem.c
|
||||
time.c
|
||||
paths.c
|
||||
|
||||
43
common/src/platform/linux/random.c
Normal file
43
common/src/platform/linux/random.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "common/random.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
bool lgRandomBytes(void * buffer, size_t size)
|
||||
{
|
||||
uint8_t * output = buffer;
|
||||
while (size)
|
||||
{
|
||||
const ssize_t received = getrandom(output, size, 0);
|
||||
if (received < 0 && errno == EINTR)
|
||||
continue;
|
||||
if (received <= 0)
|
||||
return false;
|
||||
|
||||
output += (size_t)received;
|
||||
size -= (size_t)received;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
80
common/src/platform/linux/semaphore.c
Normal file
80
common/src/platform/linux/semaphore.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "common/semaphore.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct LGSemaphore
|
||||
{
|
||||
sem_t handle;
|
||||
};
|
||||
|
||||
LGSemaphore * lgCreateSemaphore(unsigned int initialValue)
|
||||
{
|
||||
LGSemaphore * semaphore = malloc(sizeof(*semaphore));
|
||||
if (!semaphore)
|
||||
return NULL;
|
||||
|
||||
if (sem_init(&semaphore->handle, 0, initialValue) != 0)
|
||||
{
|
||||
DEBUG_ERROR("Failed to create semaphore: %s", strerror(errno));
|
||||
free(semaphore);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
void lgFreeSemaphore(LGSemaphore * semaphore)
|
||||
{
|
||||
if (!semaphore)
|
||||
return;
|
||||
|
||||
if (sem_destroy(&semaphore->handle) != 0)
|
||||
DEBUG_ERROR("Failed to destroy semaphore: %s", strerror(errno));
|
||||
free(semaphore);
|
||||
}
|
||||
|
||||
bool lgWaitSemaphore(LGSemaphore * semaphore)
|
||||
{
|
||||
int result;
|
||||
do
|
||||
result = sem_wait(&semaphore->handle);
|
||||
while (result != 0 && errno == EINTR);
|
||||
|
||||
if (result != 0)
|
||||
DEBUG_ERROR("Failed to wait on semaphore: %s", strerror(errno));
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
bool lgSignalSemaphore(LGSemaphore * semaphore)
|
||||
{
|
||||
if (sem_post(&semaphore->handle) == 0)
|
||||
return true;
|
||||
|
||||
DEBUG_ERROR("Failed to signal semaphore: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@@ -35,6 +35,8 @@ add_library(lg_common_platform_code STATIC
|
||||
sysinfo.c
|
||||
thread.c
|
||||
event.c
|
||||
semaphore.c
|
||||
random.c
|
||||
windebug.c
|
||||
ivshmem.c
|
||||
time.c
|
||||
@@ -46,6 +48,7 @@ add_library(lg_common_platform_code STATIC
|
||||
target_link_libraries(lg_common_platform_code
|
||||
lg_common
|
||||
setupapi
|
||||
bcrypt
|
||||
ntdll
|
||||
)
|
||||
|
||||
|
||||
43
common/src/platform/windows/random.c
Normal file
43
common/src/platform/windows/random.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "common/random.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
#include <bcrypt.h>
|
||||
|
||||
bool lgRandomBytes(void * buffer, size_t size)
|
||||
{
|
||||
uint8_t * output = buffer;
|
||||
while (size)
|
||||
{
|
||||
const ULONG chunk = size > ULONG_MAX ? ULONG_MAX : (ULONG)size;
|
||||
if (!BCRYPT_SUCCESS(BCryptGenRandom(
|
||||
NULL, output, chunk, BCRYPT_USE_SYSTEM_PREFERRED_RNG)))
|
||||
return false;
|
||||
|
||||
output += chunk;
|
||||
size -= chunk;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
83
common/src/platform/windows/semaphore.c
Normal file
83
common/src/platform/windows/semaphore.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "common/semaphore.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/windebug.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
struct LGSemaphore
|
||||
{
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
LGSemaphore * lgCreateSemaphore(unsigned int initialValue)
|
||||
{
|
||||
if (initialValue > (unsigned int)LONG_MAX)
|
||||
return NULL;
|
||||
|
||||
LGSemaphore * semaphore = malloc(sizeof(*semaphore));
|
||||
if (!semaphore)
|
||||
return NULL;
|
||||
|
||||
semaphore->handle = CreateSemaphoreW(
|
||||
NULL, (LONG)initialValue, LONG_MAX, NULL);
|
||||
if (!semaphore->handle)
|
||||
{
|
||||
DEBUG_WINERROR("Failed to create semaphore", GetLastError());
|
||||
free(semaphore);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
void lgFreeSemaphore(LGSemaphore * semaphore)
|
||||
{
|
||||
if (!semaphore)
|
||||
return;
|
||||
|
||||
if (!CloseHandle(semaphore->handle))
|
||||
DEBUG_WINERROR("Failed to destroy semaphore", GetLastError());
|
||||
free(semaphore);
|
||||
}
|
||||
|
||||
bool lgWaitSemaphore(LGSemaphore * semaphore)
|
||||
{
|
||||
const DWORD result = WaitForSingleObject(semaphore->handle, INFINITE);
|
||||
if (result == WAIT_OBJECT_0)
|
||||
return true;
|
||||
|
||||
DEBUG_WINERROR("Failed to wait on semaphore", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lgSignalSemaphore(LGSemaphore * semaphore)
|
||||
{
|
||||
if (ReleaseSemaphore(semaphore->handle, 1, NULL))
|
||||
return true;
|
||||
|
||||
DEBUG_WINERROR("Failed to signal semaphore", GetLastError());
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user