diff --git a/daemon/aux.h b/daemon/aux.h index 51aab5bc3..6eaa2305a 100644 --- a/daemon/aux.h +++ b/daemon/aux.h @@ -474,34 +474,40 @@ INLINE int family_from_address(const struct in6_addr *a) { } /* checks if at least one of the flags is set */ -INLINE int bf_isset(const unsigned int *u, unsigned int f) { - if ((*u & f)) +INLINE int bf_isset(const volatile unsigned int *u, unsigned int f) { + if ((g_atomic_int_get(u) & f)) return -1; return 0; } -INLINE void bf_set(unsigned int *u, unsigned int f) { - *u |= f; +INLINE void bf_set(volatile unsigned int *u, unsigned int f) { + g_atomic_int_or(u, f); } -INLINE void bf_clear(unsigned int *u, unsigned int f) { - *u &= ~f; +INLINE void bf_clear(volatile unsigned int *u, unsigned int f) { + g_atomic_int_and(u, ~f); } -INLINE void bf_xset(unsigned int *u, unsigned int f, int cond) { - bf_clear(u, f); - bf_set(u, cond ? f : 0); +INLINE void bf_set_clear(volatile unsigned int *u, unsigned int f, int cond) { + if (cond) + bf_set(u, f); + else + bf_clear(u, f); } /* works only for single flags */ -INLINE void bf_copy(unsigned int *u, unsigned int f, const unsigned int *s, unsigned int g) { - /* a good compiler will optimize out the calls to log2() */ - *u &= ~f; - if (f >= g) - *u |= (*s & g) << (int) (log2(f) - log2(g)); - else - *u |= (*s & g) >> (int) (log2(g) - log2(f)); +INLINE void bf_copy(volatile unsigned int *u, unsigned int f, + const volatile unsigned int *s, unsigned int g) +{ + bf_set_clear(u, f, bf_isset(s, g)); } /* works for multiple flags */ -INLINE void bf_copy_same(unsigned int *u, const unsigned int *s, unsigned int g) { - bf_copy(u, g, s, g); +INLINE void bf_copy_same(volatile unsigned int *u, const volatile unsigned int *s, unsigned int g) { + unsigned int old, set, clear; + old = g_atomic_int_get(s); + set = old & g; + clear = ~old & g; + bf_set(u, set); + bf_clear(u, clear); } + + INLINE void g_queue_append(GQueue *dst, const GQueue *src) { GList *l; if (!src || !dst) diff --git a/daemon/call.h b/daemon/call.h index 05c0321f1..3bd59810b 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -303,8 +303,7 @@ struct packet_stream { X509 *dtls_cert; /* LOCK: in_lock */ /* in_lock must be held for SETTING these: */ - /* (XXX replace with atomic ops where appropriate) */ - unsigned int ps_flags; + volatile unsigned int ps_flags; }; /* protected by call->master_lock, except the RO elements */ @@ -337,7 +336,7 @@ struct call_media { GSList *endpoint_maps; GHashTable *rtp_payload_types; - unsigned int media_flags; + volatile unsigned int media_flags; }; /* half a dialogue */ diff --git a/daemon/sdp.c b/daemon/sdp.c index 45820d790..2a14fe6e9 100644 --- a/daemon/sdp.c +++ b/daemon/sdp.c @@ -1123,9 +1123,9 @@ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *fl sp->type = media->media_type; memcpy(sp->direction, flags->direction, sizeof(sp->direction)); sp->desired_family = flags->address_family; - bf_xset(&sp->sp_flags, SP_FLAG_ASYMMETRIC, flags->asymmetric); - bf_xset(&sp->sp_flags, SP_FLAG_STRICT_SOURCE, flags->strict_source); - bf_xset(&sp->sp_flags, SP_FLAG_MEDIA_HANDOVER, flags->media_handover); + bf_set_clear(&sp->sp_flags, SP_FLAG_ASYMMETRIC, flags->asymmetric); + bf_set_clear(&sp->sp_flags, SP_FLAG_STRICT_SOURCE, flags->strict_source); + bf_set_clear(&sp->sp_flags, SP_FLAG_MEDIA_HANDOVER, flags->media_handover); errstr = "Invalid RTP payload types"; if (__rtp_payload_types(sp, media))