/*
Copyright 2019-2024 (C) Alexey Dynda
This file is part of Tiny Protocol Library.
GNU General Public License Usage
Protocol Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Protocol Library 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Protocol Library. If not, see .
Commercial License Usage
Licensees holding valid commercial Tiny Protocol licenses may use this file in
accordance with the commercial license agreement provided in accordance with
the terms contained in a written agreement between you and Alexey Dynda.
For further information contact via email on github account.
*/
#include
#include
#include
#include
#include
void tiny_mutex_create(tiny_mutex_t *mutex)
{
pthread_mutex_init(mutex, NULL);
}
void tiny_mutex_destroy(tiny_mutex_t *mutex)
{
pthread_mutex_destroy(mutex);
}
void tiny_mutex_lock(tiny_mutex_t *mutex)
{
pthread_mutex_lock(mutex);
}
uint8_t tiny_mutex_try_lock(tiny_mutex_t *mutex)
{
return pthread_mutex_trylock(mutex) == 0;
}
void tiny_mutex_unlock(tiny_mutex_t *mutex)
{
pthread_mutex_unlock(mutex);
}
void tiny_events_create(tiny_events_t *events)
{
events->bits = 0;
events->waiters = 0;
pthread_mutex_init(&events->mutex, NULL);
pthread_condattr_t condattr;
pthread_condattr_init(&condattr);
pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
pthread_cond_init(&events->cond, &condattr);
}
void tiny_events_destroy(tiny_events_t *events)
{
pthread_cond_destroy(&events->cond);
pthread_mutex_destroy(&events->mutex);
}
uint8_t tiny_events_wait(tiny_events_t *events, uint8_t bits, uint8_t clear, uint32_t timeout)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += timeout / 1000;
ts.tv_nsec += (timeout % 1000) * 1000000LL;
if ( ts.tv_nsec >= 1000000000LL )
{
ts.tv_nsec -= 1000000000LL;
ts.tv_sec++;
}
pthread_mutex_lock(&events->mutex);
events->waiters++;
int res = 0;
while ( (events->bits & bits) == 0 )
{
if ( timeout == 0xFFFFFFFF )
{
pthread_cond_wait(&events->cond, &events->mutex);
}
else
{
res = pthread_cond_timedwait(&events->cond, &events->mutex, &ts);
if ( res == ETIMEDOUT )
{
break;
}
}
}
uint8_t locked = 0;
if ( res != ETIMEDOUT )
{
locked = events->bits;
if ( clear )
events->bits &= ~bits;
}
events->waiters--;
pthread_mutex_unlock(&events->mutex);
return locked;
}
uint8_t tiny_events_check_int(tiny_events_t *event, uint8_t bits, uint8_t clear)
{
return tiny_events_wait(event, bits, clear, 0);
}
void tiny_events_set(tiny_events_t *events, uint8_t bits)
{
pthread_mutex_lock(&events->mutex);
events->bits |= bits;
pthread_cond_broadcast(&events->cond);
pthread_mutex_unlock(&events->mutex);
}
void tiny_events_clear(tiny_events_t *events, uint8_t bits)
{
pthread_mutex_lock(&events->mutex);
events->bits &= ~bits;
pthread_mutex_unlock(&events->mutex);
}
void tiny_sleep(uint32_t millis)
{
usleep(millis * 1000);
}
void tiny_sleep_us(uint32_t us)
{
usleep(us);
}
uint32_t tiny_millis()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec * 1000) + ts.tv_nsec / 1000000;
}
uint32_t tiny_micros()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec * 1000000) + ts.tv_nsec / 1000;
}