Skip to content

Commit

Permalink
os_funcs: Add a new allocation function, add check in proc_setup
Browse files Browse the repository at this point in the history
Add a new function to allocate an OS handler for the platform.

Check in gensio_os_proc_setup() if it has already been done, and return
an error in that case.  Check in the cleanup function and just return if
it hasn't be setup.

Signed-off-by: Corey Minyard <[email protected]>
  • Loading branch information
cminyard committed Oct 18, 2023
1 parent 4bf777d commit 790132a
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 17 deletions.
3 changes: 3 additions & 0 deletions include/gensio/gensio_os_funcs_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ extern "C" {
GENSIOOSH_DLL_PUBLIC
int gensio_default_os_hnd(int wake_sig, struct gensio_os_funcs **o);

GENSIOOSH_DLL_PUBLIC
int gensio_alloc_os_hnd(int wake_sig, struct gensio_os_funcs **o);

GENSIOOSH_DLL_PUBLIC
int gensio_os_proc_setup(struct gensio_os_funcs *o,
struct gensio_os_proc_data **data);
Expand Down
38 changes: 32 additions & 6 deletions lib/gensio_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,7 @@ gensio_unix_get_wake_sig(struct gensio_os_funcs *f)
static lock_type defos_lock = LOCK_INITIALIZER;
static struct gensio_os_funcs *defoshnd;
static int defoshnd_wake_sig = -1;
static bool proc_setup;

static struct gensio_os_funcs *
gensio_unix_get_funcs(struct gensio_os_funcs *f)
Expand Down Expand Up @@ -1758,7 +1759,11 @@ gensio_os_proc_setup(struct gensio_os_funcs *o,
struct gensio_os_proc_data *data;
sigset_t sigs;
struct sigaction sigdo;
int rv;
int rv = GE_INUSE;

LOCK(&defos_lock);
if (proc_setup)
goto out;

data = &proc_data;
data->o = o;
Expand All @@ -1781,7 +1786,7 @@ gensio_os_proc_setup(struct gensio_os_funcs *o,
rv = sigprocmask(SIG_BLOCK, &sigs, &data->old_sigs);
if (rv) {
rv = gensio_os_err_to_err(o, errno);
return rv;
goto out;
}
data->wait_sigs = data->old_sigs;
if (data->wake_sig)
Expand All @@ -1800,7 +1805,7 @@ gensio_os_proc_setup(struct gensio_os_funcs *o,
if (rv) {
rv = gensio_os_err_to_err(o, errno);
sigprocmask(SIG_SETMASK, &data->old_sigs, NULL);
return rv;
goto out;
}

if (data->wake_sig) {
Expand All @@ -1811,7 +1816,7 @@ gensio_os_proc_setup(struct gensio_os_funcs *o,
rv = gensio_os_err_to_err(o, errno);
sigaction(SIGCHLD, &data->old_sigchld, NULL);
sigprocmask(SIG_SETMASK, &data->old_sigs, NULL);
return rv;
goto out;
}
}

Expand All @@ -1821,13 +1826,16 @@ gensio_os_proc_setup(struct gensio_os_funcs *o,
sigprocmask(SIG_SETMASK, &data->old_sigs, NULL);
if (data->wake_sig)
sigaction(data->wake_sig, &data->old_wakesig, NULL);
return rv;
goto out;
}

LOCK_INIT(&data->handler_lock);

*rdata = data;
return 0;
proc_setup = true;
out:
UNLOCK(&defos_lock);
return rv;
}

void
Expand Down Expand Up @@ -1877,6 +1885,12 @@ check_for_sigpending(sigset_t *check_for)
void
gensio_os_proc_cleanup(struct gensio_os_proc_data *data)
{
LOCK(&defos_lock);
if (!proc_setup)
goto out;

proc_setup = false;

/* We should be single-threaded here. */
while (data->cleanup_handlers) {
struct gensio_os_cleanup_handler *h = data->cleanup_handlers;
Expand Down Expand Up @@ -1912,6 +1926,9 @@ gensio_os_proc_cleanup(struct gensio_os_proc_data *data)
;

sigprocmask(SIG_SETMASK, &data->old_sigs, NULL);
out:
UNLOCK(&defos_lock);
return;
}

void
Expand Down Expand Up @@ -2359,6 +2376,15 @@ gensio_default_os_hnd(int wake_sig, struct gensio_os_funcs **o)
return err;
}

int
gensio_alloc_os_hnd(int wake_sig, struct gensio_os_funcs **o)
{
if (wake_sig == -198234)
wake_sig = SIGUSR1;

return gensio_unix_funcs_alloc(NULL, wake_sig, o);
}

void
gensio_osfunc_exit(int rv)
{
Expand Down
43 changes: 33 additions & 10 deletions lib/gensio_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -3935,41 +3935,51 @@ struct gensio_os_proc_data {
struct gensio_os_cleanup_handler *cleanup_handlers;
};
static struct gensio_os_proc_data proc_data;
bool proc_setup;

int
gensio_os_proc_setup(struct gensio_os_funcs *o,
struct gensio_os_proc_data **data)
{
int rv;
int rv = GE_INUSE;
HRESULT res;

AcquireSRWLockExclusive(&def_win_os_funcs_lock);
if (proc_setup)
goto out;

rv = 0;
res = CoInitializeEx(NULL, COINIT_MULTITHREADED);
switch (res) {
case S_OK: case S_FALSE:
break;
case RPC_E_CHANGED_MODE: return GE_INCONSISTENT;
case E_INVALIDARG: return GE_INVAL;
case E_OUTOFMEMORY: return GE_NOMEM;
case E_UNEXPECTED: default: return GE_OSERR;
case S_OK: case S_FALSE: break;
case RPC_E_CHANGED_MODE: rv = GE_INCONSISTENT; break;
case E_INVALIDARG: rv = GE_INVAL; break;
case E_OUTOFMEMORY: rv = GE_NOMEM; break;
case E_UNEXPECTED: default: rv = GE_OSERR; break;
}
if (rv)
goto out;

proc_data.global_waiter = CreateSemaphoreA(NULL, 0, 1000000, NULL);
if (!proc_data.global_waiter) {
CoUninitialize();
return GE_NOMEM;
rv = GE_NOMEM;
goto out;
}

rv = o->control(o, GENSIO_CONTROL_SET_PROC_DATA, &proc_data, NULL);
if (rv) {
CloseHandle(proc_data.global_waiter);
CoUninitialize();
proc_data.global_waiter = NULL;
return rv;
goto out;
}
LOCK_INIT(&proc_data.lock);
proc_data.o = o;
*data = &proc_data;
return 0;
out:
ReleaseSRWLockExclusive(&def_win_os_funcs_lock);
return rv;
}

static void
Expand Down Expand Up @@ -4053,6 +4063,11 @@ gensio_register_os_cleanup_handler(struct gensio_os_funcs *o,
void
gensio_os_proc_cleanup(struct gensio_os_proc_data *data)
{
AcquireSRWLockExclusive(&def_win_os_funcs_lock);
if (!proc_setup)
goto out;

proc_setup = false;
/* We should be single-threaded here. */
while (data->cleanup_handlers) {
struct gensio_os_cleanup_handler *h = data->cleanup_handlers;
Expand All @@ -4075,6 +4090,8 @@ gensio_os_proc_cleanup(struct gensio_os_proc_data *data)
}
LOCK_DESTROY(&proc_data.lock);
CoUninitialize();
out:
ReleaseSRWLockExclusive(&def_win_os_funcs_lock);
}

HANDLE
Expand Down Expand Up @@ -4283,6 +4300,12 @@ gensio_default_os_hnd(int wake_sig, struct gensio_os_funcs **o)
return 0;
}

int
gensio_alloc_os_hnd(int wake_sig, struct gensio_os_funcs **o)
{
return gensio_win_funcs_alloc(o);
}

void
gensio_osfunc_exit(int rv)
{
Expand Down
18 changes: 17 additions & 1 deletion man/gensio_os_funcs.3
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ by the gensio library
.PP
.B int gensio_default_os_hnd(int wake_sig, struct gensio_os_funcs **o)
.PP
.B int gensio_alloc_os_hnd(int wake_sig, struct gensio_os_funcs **o)
.PP
.B int gensio_unix_funcs_alloc(struct selector_s *sel, int wake_sig,
.br
struct gensio_os_funcs **o)
Expand Down Expand Up @@ -218,11 +220,20 @@ the gensio library with one of these. Even though it's a bit of a
pain to have to pass one of these around, it adds needed flexibility.

.B gensio_default_os_hnd
provides a way to allocate a default OS function handler for the
provides a way to get the default OS function handler for the
platform. The same value will be returned each time, only one is
created. You should generally use this one unless you have a special
need as documented above.

.B gensio_alloc_os_hnd
allocates a new OS handler for the platform, for Unix or Windows.
Multiple OS handlers can be used to handle different I/O at different
priorities. When you create a gensio, all I/O callbacks will be
handled from the OS handler used to create it. So you can run
different OS handlers in threads of different priority to run
different gensios at different priority. Otherwise there is not much
reason to do this.

The
.I wait_sig
parameter usage on Windows is unused. For Unix systems, this signal
Expand Down Expand Up @@ -308,6 +319,11 @@ into that. If you want to modify the wait signal mask, you can use
.I gensio_os_proc_unix_get_wait_sigset
to fetch a pointer to it and modify it.

Note that if you call this more than once without calling
.I gensio_os_proc_cleanup
inbetween, it will return
.I GE_INUSE.

The
.I gensio_os_proc_cleanup
function undoes all the changes
Expand Down

0 comments on commit 790132a

Please sign in to comment.