4#include <click/machine.hh>
5#include <click/glue.hh>
7#if CLICK_LINUXMODULE || (CLICK_USERLEVEL && HAVE_MULTITHREAD)
8# define CLICK_MULTITHREAD_SPINLOCK 1
10#if CLICK_USERLEVEL && !NDEBUG
11# define SPINLOCK_ASSERTLEVEL "<-999>"
13# define SPINLOCK_ASSERTLEVEL "<1>"
63 typedef struct A_t AT;
65 void initialize(
unsigned int n, T v) {
67 storage = CLICK_ALIGNED_NEW(AT,_size);
68 for (
unsigned i = 0; i < n; i++) {
77 _size = click_max_cpu_ids();
78 storage = CLICK_ALIGNED_NEW(AT,_size);
79 for (
unsigned i = 0; i < _size; i++) {
80 new (&storage[i].v) T;
85 initialize(click_max_cpu_ids(),v);
97 void resize(
unsigned int max_cpu_id, T v) {
98 CLICK_ALIGNED_DELETE(storage, AT, _size);
99 initialize(max_cpu_id,v);
104 CLICK_ALIGNED_DELETE(storage,AT,_size);
109 inline T* operator->()
const {
110 return &(storage[click_current_cpu_id()].v);
113 return storage[click_current_cpu_id()].v;
116 inline T& operator+=(
const T& add)
const {
117 storage[click_current_cpu_id()].v += add;
118 return storage[click_current_cpu_id()].v;
121 inline T& operator++()
const {
122 return ++(storage[click_current_cpu_id()].v);
125 inline T operator++(
int)
const {
126 return storage[click_current_cpu_id()].v++;
129 inline T& operator--()
const {
130 return --(storage[click_current_cpu_id()].v);
133 inline T operator--(
int)
const {
134 return storage[click_current_cpu_id()].v--;
137 inline T& operator=(T value)
const {
138 storage[click_current_cpu_id()].v = value;
139 return storage[click_current_cpu_id()].v;
143 if (_size != pt._size) {
145 CLICK_ALIGNED_DELETE(storage,AT, _size);
146 storage = CLICK_ALIGNED_NEW(AT, _size);
148 for (
int i = 0; i < pt.
weight(); i++) {
149 storage[i] = pt.storage[i];
153 inline void set(T v) {
154 storage[click_current_cpu_id()].v = v;
157 inline void setAll(T v) {
158 for (
int i = 0; i < click_max_cpu_ids(); i++)
162 inline T& get()
const{
163 return storage[click_current_cpu_id()].v;
166 inline const T& cst()
const{
167 return storage[click_current_cpu_id()].v;
177 return storage[thread_id].v;
180 inline void set_value_for_thread(
int thread_id, T v) {
181 storage[thread_id].v = v;
194 inline void set_value(
int i, T v) {
195 set_value_for_thread(i, v);
207 inline unsigned int get_mapping(
int i) {
211 class const_iterator {
public:
221 bool operator!=(
const const_iterator &o)
const {
222 return _pos != o._pos;
229 const_iterator begin()
const {
230 return const_iterator(
this,0);
233 const_iterator end()
const {
234 return const_iterator(
this,_size);
237 class iterator {
public:
247 bool operator!=(
const iterator &o)
const {
248 return _pos != o._pos;
256 return iterator(
this,0);
260 return iterator(
this,_size);
282 inline T* operator->() {
287 inline T& operator*() {
295 inline const T& cst()
const {
299 inline constexpr int weight()
const {
303 inline T& get_value(
int) {
307 class const_iterator {
public:
317 bool operator!=(
const const_iterator &o)
const {
318 return _pos != o._pos;
325 const_iterator begin()
const {
326 return const_iterator(
this,0);
329 const_iterator end()
const {
330 return const_iterator(
this, 1);
333 class iterator {
public:
343 bool operator!=(
const iterator &o)
const {
344 return _pos != o._pos;
352 return iterator(
this,0);
356 return iterator(
this, 1);
363#define PER_THREAD_SET(pt,value) \
364 for (unsigned i = 0; i < pt.weight(); i++) { \
365 pt.set_value(i, value); \
368#define PER_THREAD_POINTER_SET(pt,member,value) \
369 for (unsigned i = 0; i < pt.weight(); i++) { \
370 pt.get_value(i)->member = value; \
373#define PER_THREAD_MEMBER_SET(pt,member,value) \
374 for (unsigned i = 0; i < pt.weight(); i++) { \
375 pt.get_value(i).member = value; \
378#define PER_THREAD_VECTOR_SET(pt,member,value) \
379 for (unsigned i = 0; i < pt.weight(); i++) { \
380 for (int j = 0; j < pt.get_value(i).size(); j++) \
381 (pt.get_value(i))[j].member = value; \
384#define PER_THREAD_SUM(type, var, pt) \
386 for (unsigned i = 0; i < pt.weight(); i++) { \
387 var += pt.get_value(i); \
390#define PER_THREAD_POINTER_SUM(type, var, pt, member) \
392 for (unsigned i = 0; i < pt.weight(); i++) { \
393 var += pt.get_value(i)->member; \
396#define PER_THREAD_MEMBER_SUM(type, var, pt, member) \
398 for (unsigned i = 0; i < pt.weight(); i++) { \
399 var += pt.get_value(i).member; \
402#define PER_THREAD_VECTOR_SUM(type, var, pt, index, member) \
404 for (unsigned i = 0; i < pt.weight(); i++) { \
405 var += pt.get_value(i)[index].member; \
447 inline bool nested()
const;
449#if CLICK_MULTITHREAD_SPINLOCK
454 click_processor_t _owner;
462#if CLICK_MULTITHREAD_SPINLOCK
463 : _depth(0), _owner(click_invalid_processor())
466#if CLICK_MULTITHREAD_SPINLOCK
474#if CLICK_MULTITHREAD_SPINLOCK
476 click_chatter(SPINLOCK_ASSERTLEVEL
"Spinlock::~Spinlock(): assertion \"_depth == 0\" failed");
490#if CLICK_MULTITHREAD_SPINLOCK
491 click_processor_t my_cpu = click_get_processor();
492 if (_owner != my_cpu) {
493 while (_lock.swap(1) != 0)
496 }
while (_lock != 0);
512#if CLICK_MULTITHREAD_SPINLOCK
513 click_processor_t my_cpu = click_get_processor();
514 if (_owner != my_cpu) {
515 if (_lock.swap(1) != 0) {
516 click_put_processor();
536#if CLICK_MULTITHREAD_SPINLOCK
537 if (unlikely(_owner != click_current_processor()))
538 click_chatter(SPINLOCK_ASSERTLEVEL
"Spinlock::release(): assertion \"owner == click_current_processor()\" failed");
539 if (likely(_depth > 0)) {
541 _owner = click_invalid_processor();
545 click_chatter(SPINLOCK_ASSERTLEVEL
"Spinlock::release(): assertion \"_depth > 0\" failed");
546 click_put_processor();
556#if CLICK_MULTITHREAD_SPINLOCK
599#elif CLICK_MULTITHREAD_SPINLOCK
611 spin_lock_init(&_lock);
612#elif CLICK_MULTITHREAD_SPINLOCK
618SimpleSpinlock::~SimpleSpinlock()
632#elif CLICK_MULTITHREAD_SPINLOCK
633 while (_lock.swap(1) != 0) {
636 }
while (_lock != 0);
651 return spin_trylock(&_lock);
652#elif CLICK_MULTITHREAD_SPINLOCK
653 return _lock.swap(1) == 0;
669#elif CLICK_MULTITHREAD_SPINLOCK
702 typedef unsigned long flags_t;
707 inline flags_t
acquire() CLICK_ALWAYS_INLINE;
708 inline void release(flags_t) CLICK_ALWAYS_INLINE;
713#elif CLICK_USERLEVEL && HAVE_MULTITHREAD
725 spin_lock_init(&_lock);
732inline SpinlockIRQ::flags_t
737 spin_lock_irqsave(&_lock, flags);
739#elif CLICK_USERLEVEL && HAVE_MULTITHREAD
754 spin_unlock_irqrestore(&_lock, flags);
755#elif CLICK_USERLEVEL && HAVE_MULTITHREAD
825ReadWriteLock::~ReadWriteLock()
858 click_put_processor();
876 click_put_processor();
893 for (
unsigned i = 0; i < _l.
weight(); i++)
914 for (i = 0; i < (unsigned) _l.
weight(); i++) {
921 for (
unsigned j = 0; j < i; j++)
942 for (
unsigned i = 0; i < _l.
weight(); i++)
955 inline void acquire() {};
957 inline void release() {};
959 inline bool attempt() {
return true; };
961 inline void read_begin() {}
963 inline void read_end() {}
965 inline void read_get() {}
967 inline void write_begin() {}
969 inline void write_end() {}
971 inline void set_max_writers(
int) {}
975#undef SPINLOCK_ASSERTLEVEL
An atomic 32-bit integer.
A read/write lock.
Definition sync.hh:800
void release_write()
Releases the ReadWriteLock for writing.
Definition sync.hh:939
ReadWriteLock()
Creates a ReadWriteLock.
Definition sync.hh:820
bool attempt_read()
Attempts to acquire the ReadWriteLock for reading.
Definition sync.hh:853
void release_read()
Releases the ReadWriteLock for reading.
Definition sync.hh:872
void acquire_write()
Acquires the ReadWriteLock for writing.
Definition sync.hh:890
bool attempt_write()
Attempts to acquire the ReadWriteLock for writing.
Definition sync.hh:909
void acquire_read()
Acquires the ReadWriteLock for reading.
Definition sync.hh:839
A non-recursive spinlock for SMP Click threads.
Definition sync.hh:587
bool attempt()
Attempts to acquire the SimpleSpinlock.
Definition sync.hh:648
void release()
Releases the SimpleSpinlock.
Definition sync.hh:665
SimpleSpinlock()
Create a SimpleSpinlock.
Definition sync.hh:608
void acquire()
Acquires the SimpleSpinlock.
Definition sync.hh:628
A recursive spinlock for SMP Click threads.
Definition sync.hh:439
void release()
Releases the Spinlock.
Definition sync.hh:534
bool attempt()
Attempts to acquire the Spinlock.
Definition sync.hh:510
void acquire()
Acquires the Spinlock.
Definition sync.hh:488
Spinlock()
Create a Spinlock.
Definition sync.hh:461
bool nested() const
Returns true iff the Spinlock has been acquired more than once by the current thread.
Definition sync.hh:554
A spinlock that disables interrupts.
Definition sync.hh:697
flags_t acquire() CLICK_ALWAYS_INLINE
Acquires the SpinlockIRQ.
Definition sync.hh:733
void release(flags_t) CLICK_ALWAYS_INLINE
Releases the SpinlockIRQ.
Definition sync.hh:751
SpinlockIRQ()
Creates a SpinlockIRQ.
Definition sync.hh:722
A 32-bit integer with support for atomic operations.
Definition atomic.hh:71
unsigned weight() const
Definition sync.hh:203
void resize(unsigned int max_cpu_id, T v)
Definition sync.hh:97
T & get_value_for_thread(int thread_id) const
Definition sync.hh:176
T & get_value(int i) const
Definition sync.hh:190
Timestamp operator*(const Timestamp &a, double b)
Scale a by a factor of b and return the result.
Definition timestamp.hh:1447