struct port_range {
int size, get, put_h, put_t; /* range size, and get/put positions */
+ int refcount;
uint16_t ports[VAR_ARRAY]; /* array of <size> ports, in host byte order */
};
#define GET_NEXT_OFF(range, off) ((off) == (range)->size - 1 ? 0 : (off) + 1)
+static inline void port_range_release(struct port_range *range)
+{
+ if (range) {
+ int refcount = _HA_ATOMIC_SUB_FETCH(&range->refcount, 1);
+
+ BUG_ON(refcount < 0);
+ if (refcount == 0)
+ free(range);
+ }
+}
+
/* return an available port from range <range>, or zero if none is left */
static inline int port_range_alloc_port(struct port_range *range)
{
return 0;
ret = range->ports[get];
} while (!(_HA_ATOMIC_CAS(&range->get, &get, GET_NEXT_OFF(range, get))));
+ _HA_ATOMIC_INC(&range->refcount);
return ret;
}
* can use that port.
*/
_HA_ATOMIC_STORE(&range->put_t, GET_NEXT_OFF(range, put));
+ port_range_release(range);
}
/* return a new initialized port range of N ports. The ports are not
if (!ret)
return NULL;
ret->size = n + 1;
+ ret->refcount = 1;
/* Start at the first free element */
ret->put_h = ret->put_t = n;
return ret;
ha_free(&srv_tlv->fmt_string);
ha_free(&srv_tlv);
}
+ port_range_release(srv->conn_src.sport_range);
}
/* Deallocate a server <srv> and its member. <srv> must be allocated. For