| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This function (or of similar nature) is required to safely use a refcnt
and smr_entry together. Such functions exist on other platforms as
kref_get_unless_zero (on Linux) and refcount_acquire_if_gt (on FreeBSD).
The following diagram details the following situation with and without
refcnt_take_if_gt in 3 cases, with the first showing the "invalid" use
of refcnt_take.
Situation:
Thread #1 is removing the global referenc (o).
Thread #2 wants to reference an object (r), using a thread pointer (t).
Case:
1) refcnt_take after Thread #1 has released "o"
2) refcnt_take_if_gt before Thread #1 has released "o"
3) refcnt_take_if_gt after Thread #1 has released "o"
Data:
struct obj {
struct smr_entry smr;
struct refcnt refcnt;
} *o, *r, *t1, *t2;
Thread #1 | Thread #2
---------------------------------+------------------------------------
| r = NULL;
rw_enter_write(&lock); | smr_read_enter();
|
t1 = SMR_PTR_GET_LOCKED(&o); | t2 = SMR_PTR_GET(&o);
SMR_PTR_SET_LOCKED(&o, NULL); |
|
if (refcnt_rele(&t1->refcnt) |
smr_call(&t1->smr, free, t1); |
| if (t2 != NULL) {
| refcnt_take(&t2->refcnt);
| r = t2;
| }
rw_exit_write(&lock); | smr_read_exit();
.....
// called by smr_thread |
free(t1); |
.....
| // use after free
| *r
---------------------------------+------------------------------------
| r = NULL;
rw_enter_write(&lock); | smr_read_enter();
|
t1 = SMR_PTR_GET_LOCKED(&o); | t2 = SMR_PTR_GET(&o);
SMR_PTR_SET_LOCKED(&o, NULL); |
|
if (refcnt_rele(&t1->refcnt) |
smr_call(&t1->smr, free, t1); |
| if (t2 != NULL &&
| refcnt_take_if_gt(&t2->refcnt, 0))
| r = t2;
rw_exit_write(&lock); | smr_read_exit();
.....
// called by smr_thread | // we don't have a valid reference
free(t1); | assert(r == NULL);
---------------------------------+------------------------------------
| r = NULL;
rw_enter_write(&lock); | smr_read_enter();
|
t1 = SMR_PTR_GET_LOCKED(&o); | t2 = SMR_PTR_GET(&o);
SMR_PTR_SET_LOCKED(&o, NULL); |
| if (t2 != NULL &&
| refcnt_take_if_gt(&t2->refcnt, 0))
| r = t2;
if (refcnt_rele(&t1->refcnt) |
smr_call(&t1->smr, free, t1); |
rw_exit_write(&lock); | smr_read_exit();
.....
| // we need to put our reference
| if (refcnt_rele(&t2->refcnt))
| smr_call(&t2->smr, free, t2);
.....
// called by smr_thread |
free(t1); |
---------------------------------+------------------------------------
Currently it uses atomic_add_int_nv to atomically read the refcnt,
but I'm open to suggestions for better ways.
The atomic_cas_uint is used to ensure that refcnt hasn't been modified
since reading `old`.
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
case when requested table is already exists.
Except initialization time, route_output() and if_createrdomain() are the
only paths where we call rtable_add(9). We check requested table existence
by rtable_exists(9) and it's not the error condition if the table exists.
Otherwise we are trying to create requested table by rtable_add(9). Those
paths are kernel locked so concurrent thread can't create requested table
just after rtable_exists(9) check. Also rtable_add(9) has internal
rtable_exists(9) check and in this case the table existence assumed as
EEXIST error. This error path is never reached.
We are going to unlock PF_ROUTE sockets. This means route_output() will
not be serialized with if_createrdomain() and concurrent thread could
create requested table. Table existence check and creation should be
serialized and it makes sense to do this within rtable_add(9). This time
kernel lock is used for this so it pushed down to rtable_add(9). The
internal rtable_exists(9) check was modified and table existence is not
error now.
Since the external rtable_exists(9) check is useless it was removed from
if_createrdomain(). It still exists in route_output() path because the
logic is more complicated here.
ok mpi@
|
|
|
|
| |
OK kn@
|
|
|
|
| |
Patch from Josh Rickmar. Ty jrick!
|
| |
|
| |
|
|
|
|
| |
Suspend/resume and other power events are NOT YET SUPPORTED.
|
| |
|
|
|
|
| |
from me
|
|
|
|
|
|
|
|
|
|
| |
Use of the IOCTL section losely adopted from bridge(4),
the list of ioctls however is still incomplete.
mpw(4) and mpip(4) could use a reference to mpe(4) IOCTL or so,
but this is good enough for starters.
Feedback OK claudio
|
| |
|
|
|
|
| |
With help from sthen@. OK sthen@ jmc@
|
| |
|
|
|
|
| |
noticed another change
|
|
|
|
| |
"good idea" sthen
|
| |
|
|
|
|
|
| |
allocation. not the perfect text yet, but it is better.
discussed with florian and jmc
|
| |
|
|
|
|
|
| |
that isn't directly usable to a shorter table and example of what one might
need to add to EXTRACT_CASES when making a change; ok espie@
|
|
|
|
|
|
| |
disabled it in the past and then note that IPv6 autoconfiguration
doesn't work for you, you will quickly note that we will point and
laugh.
|
| |
|
| |
|
|
|
|
|
|
| |
and installing USD/SMM/PSD docs.
jmc@ agrees with the direction, ok millert@ on an earlier diff
|
| |
|
|
|
|
|
|
| |
Thanks to RJ Johnson for this work!
ok mpi@
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
| |
submitted the diff for the previous commit and who i forgot to credit...
|
|
|
|
|
|
| |
tweaked by deraadt
ok kettenis deraadt
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
the go ecosystem).
Properly handle failing daemon startup now that we have pipefail.
To take advantage of this new feature, just add foo_logger=facility to the
daemon rc.d(8) script or in rc.conf.local(8) or use rcctl:
rcctl set foo logger daemon.info
tweak for checking flags in rcctl(8) from martijn@
"this looks pretty good" deraadt@
ok sthen@
|
| |
|
| |
|
|
|
|
| |
mention that shell wildcards may be used.
|
| |
|
| |
|
| |
|
|
|
|
|
|
| |
a monster.
okay sthen@
|
|
|
|
|
|
|
| |
i'm not a fan of having to cast to caddr_t when we have modern
inventions like void *s we can take advantage of.
ok claudio@ mvs@ bluhm@
|