diff options
author | Cem Keylan <cem@ckyln.com> | 2020-10-16 17:41:25 +0300 |
---|---|---|
committer | Cem Keylan <cem@ckyln.com> | 2020-10-16 17:41:25 +0300 |
commit | e2abcdca396661cbe0ae2ddb13d5c2b85682c13a (patch) | |
tree | acf9b5c80b645617f882c45224c6e07251711842 /sys/sys/srp.h | |
download | otools-e2abcdca396661cbe0ae2ddb13d5c2b85682c13a.tar.gz |
initial commit
Diffstat (limited to 'sys/sys/srp.h')
-rw-r--r-- | sys/sys/srp.h | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/sys/sys/srp.h b/sys/sys/srp.h new file mode 100644 index 0000000..a22e940 --- /dev/null +++ b/sys/sys/srp.h @@ -0,0 +1,190 @@ +/* $OpenBSD: srp.h,v 1.14 2019/03/31 14:03:40 mpi Exp $ */ + +/* + * Copyright (c) 2014 Jonathan Matthew <jmatthew@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_SRP_H_ +#define _SYS_SRP_H_ + +#include <sys/refcnt.h> + +#ifndef __upunused +#ifdef MULTIPROCESSOR +#define __upunused +#else +#define __upunused __attribute__((__unused__)) +#endif +#endif /* __upunused */ + +struct srp { + void *ref; +}; + +#define SRP_INITIALIZER() { NULL } + +struct srp_hazard { + struct srp *sh_p; + void *sh_v; +}; + +struct srp_ref { + struct srp_hazard *hz; +} __upunused; + +#define SRP_HAZARD_NUM 16 + +struct srp_gc { + void (*srp_gc_dtor)(void *, void *); + void *srp_gc_cookie; + struct refcnt srp_gc_refcnt; +}; + +#define SRP_GC_INITIALIZER(_d, _c) { (_d), (_c), REFCNT_INITIALIZER() } + +/* + * singly linked list built by following srps + */ + +struct srpl_rc { + void (*srpl_ref)(void *, void *); + struct srp_gc srpl_gc; +}; +#define srpl_cookie srpl_gc.srp_gc_cookie + +#define SRPL_RC_INITIALIZER(_r, _u, _c) { _r, SRP_GC_INITIALIZER(_u, _c) } + +struct srpl { + struct srp sl_head; +}; + +#define SRPL_HEAD(name, type) struct srpl + +#define SRPL_ENTRY(type) \ +struct { \ + struct srp se_next; \ +} + +#ifdef _KERNEL + +void srp_startup(void); +void srp_gc_init(struct srp_gc *, void (*)(void *, void *), void *); +void *srp_swap_locked(struct srp *, void *); +void srp_update_locked(struct srp_gc *, struct srp *, void *); +void *srp_get_locked(struct srp *); +void srp_gc_finalize(struct srp_gc *); + +void srp_init(struct srp *); + +#ifdef MULTIPROCESSOR +void *srp_swap(struct srp *, void *); +void srp_update(struct srp_gc *, struct srp *, void *); +void srp_finalize(void *, const char *); +void *srp_enter(struct srp_ref *, struct srp *); +void *srp_follow(struct srp_ref *, struct srp *); +void srp_leave(struct srp_ref *); +#else /* MULTIPROCESSOR */ +#define srp_swap(_srp, _v) srp_swap_locked((_srp), (_v)) +#define srp_update(_gc, _srp, _v) srp_update_locked((_gc), (_srp), (_v)) +#define srp_finalize(_v, _wchan) ((void)0) +#define srp_enter(_sr, _srp) ((_srp)->ref) +#define srp_follow(_sr, _srp) ((_srp)->ref) +#define srp_leave(_sr) do { } while (0) +#endif /* MULTIPROCESSOR */ + + +void srpl_rc_init(struct srpl_rc *, void (*)(void *, void *), + void (*)(void *, void *), void *); + +#define SRPL_INIT(_sl) srp_init(&(_sl)->sl_head) + +#define SRPL_FIRST(_sr, _sl) srp_enter((_sr), &(_sl)->sl_head) +#define SRPL_NEXT(_sr, _e, _ENTRY) srp_enter((_sr), &(_e)->_ENTRY.se_next) +#define SRPL_FOLLOW(_sr, _e, _ENTRY) srp_follow((_sr), &(_e)->_ENTRY.se_next) + +#define SRPL_FOREACH(_c, _sr, _sl, _ENTRY) \ + for ((_c) = SRPL_FIRST(_sr, _sl); \ + (_c) != NULL; \ + (_c) = SRPL_FOLLOW(_sr, _c, _ENTRY)) + +#define SRPL_LEAVE(_sr) srp_leave((_sr)) + +#define SRPL_FIRST_LOCKED(_sl) srp_get_locked(&(_sl)->sl_head) +#define SRPL_EMPTY_LOCKED(_sl) (SRPL_FIRST_LOCKED(_sl) == NULL) + +#define SRPL_NEXT_LOCKED(_e, _ENTRY) \ + srp_get_locked(&(_e)->_ENTRY.se_next) + +#define SRPL_FOREACH_LOCKED(_c, _sl, _ENTRY) \ + for ((_c) = SRPL_FIRST_LOCKED(_sl); \ + (_c) != NULL; \ + (_c) = SRPL_NEXT_LOCKED((_c), _ENTRY)) + +#define SRPL_FOREACH_SAFE_LOCKED(_c, _sl, _ENTRY, _tc) \ + for ((_c) = SRPL_FIRST_LOCKED(_sl); \ + (_c) && ((_tc) = SRPL_NEXT_LOCKED(_c, _ENTRY), 1); \ + (_c) = (_tc)) + +#define SRPL_INSERT_HEAD_LOCKED(_rc, _sl, _e, _ENTRY) do { \ + void *head; \ + \ + srp_init(&(_e)->_ENTRY.se_next); \ + \ + head = SRPL_FIRST_LOCKED(_sl); \ + if (head != NULL) { \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, head); \ + srp_update_locked(&(_rc)->srpl_gc, \ + &(_e)->_ENTRY.se_next, head); \ + } \ + \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, _e); \ + srp_update_locked(&(_rc)->srpl_gc, &(_sl)->sl_head, (_e)); \ +} while (0) + +#define SRPL_INSERT_AFTER_LOCKED(_rc, _se, _e, _ENTRY) do { \ + void *next; \ + \ + srp_init(&(_e)->_ENTRY.se_next); \ + \ + next = SRPL_NEXT_LOCKED(_se, _ENTRY); \ + if (next != NULL) { \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, next); \ + srp_update_locked(&(_rc)->srpl_gc, \ + &(_e)->_ENTRY.se_next, next); \ + } \ + \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, _e); \ + srp_update_locked(&(_rc)->srpl_gc, \ + &(_se)->_ENTRY.se_next, (_e)); \ +} while (0) + +#define SRPL_REMOVE_LOCKED(_rc, _sl, _e, _type, _ENTRY) do { \ + struct srp *ref; \ + struct _type *c, *n; \ + \ + ref = &(_sl)->sl_head; \ + while ((c = srp_get_locked(ref)) != (_e)) \ + ref = &c->_ENTRY.se_next; \ + \ + n = SRPL_NEXT_LOCKED(c, _ENTRY); \ + if (n != NULL) \ + (_rc)->srpl_ref(&(_rc)->srpl_cookie, n); \ + srp_update_locked(&(_rc)->srpl_gc, ref, n); \ + srp_update_locked(&(_rc)->srpl_gc, &c->_ENTRY.se_next, NULL); \ +} while (0) + +#endif /* _KERNEL */ + +#endif /* _SYS_SRP_H_ */ |