mirror of
https://github.com/haproxy/haproxy.git
synced 2026-06-13 10:50:16 -04:00
MINOR: tasks: Introduce __task_set_state_and_tid
Introduce a new function, __task_set_state_and_tid, that atomically can set a task's state and its tid. This will be used later, as the tid will be used to indicate task ownership even for shared tasks.
This commit is contained in:
parent
92206fb02f
commit
91f9e3a3dd
2 changed files with 61 additions and 0 deletions
|
|
@ -205,6 +205,63 @@ static inline uint64_t task_mono_time(void)
|
|||
return th_ctx->sched_call_date;
|
||||
}
|
||||
|
||||
#if !defined(HA_CAS_IS_8B) && !defined(HA_HAVE_CAS_DW)
|
||||
__decl_thread(extern HA_SPINLOCK_T task_state_tid);
|
||||
#endif
|
||||
|
||||
static inline int __task_set_state_and_tid(struct task *t, int expected_tid, int new_tid, unsigned int current, unsigned int wanted)
|
||||
{
|
||||
#if defined(HA_CAS_IS_8B) || defined(HA_HAVE_CAS_DW)
|
||||
uint64_t expected_value;
|
||||
uint64_t new_value;
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
expected_value = ((uint64_t)(current) << 32) | (uint32_t)expected_tid;
|
||||
#else
|
||||
expected_value = current | ((uint64_t)expected_tid << 32);
|
||||
#endif
|
||||
do {
|
||||
int tid_seen;
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
tid_seen = (expected_value & 0xffffffff);
|
||||
if (tid_seen != expected_tid)
|
||||
return 0;
|
||||
if ((expected_value >> 32) != current)
|
||||
return 0;
|
||||
new_value = ((uint64_t)wanted << 32) | (uint32_t)new_tid;
|
||||
|
||||
#else
|
||||
tid_seen = (expected_value >> 32);
|
||||
if (tid_seen != expected_tid)
|
||||
return 0;
|
||||
if ((expected_value & 0xffffffff) != current)
|
||||
return 0;
|
||||
new_value = wanted | ((uint64_t)new_tid << 32);
|
||||
#endif
|
||||
#if defined(HA_CAS_IS_8B)
|
||||
} while (!HA_ATOMIC_CAS((uint64_t *)&t->state, &expected_value, new_value) && __ha_cpu_relax());
|
||||
#elif defined(HA_HAVE_CAS_DW)
|
||||
} while (!HA_ATOMIC_DWCAS((uint64_t *)&t->state, &expected_value, &new_value) && __ha_cpu_relax());
|
||||
#endif
|
||||
return 1;
|
||||
#else /* !HA_CAS_IS_8B && !HA_HAVE_CAS_DW */
|
||||
int old_state;
|
||||
int ret = 0;
|
||||
|
||||
HA_SPIN_LOCK(OTHER_LOCK, &task_state_tid);
|
||||
if (_HA_ATOMIC_LOAD(&t->tid) == expected_tid) {
|
||||
old_state = _HA_ATOMIC_LOAD(&t->state);
|
||||
if (old_state == current && HA_ATOMIC_CAS(&t->state, &old_state, wanted)) {
|
||||
_HA_ATOMIC_STORE(&t->tid, new_tid);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
HA_SPIN_UNLOCK(OTHER_LOCK, &task_state_tid);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* puts the task <t> in run queue with reason flags <f>, and returns <t> */
|
||||
/* This will put the task in the local runqueue if the task is only runnable
|
||||
* by the current thread, in the global runqueue otherwies. With DEBUG_TASK,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ static struct {
|
|||
int sched_stuck THREAD_ALIGNED();
|
||||
} sched_ctx[MAX_THREADS];
|
||||
|
||||
#if !defined(HA_CAS_IS_8B) && !defined(HA_HAVE_CAS_DW)
|
||||
__decl_thread(HA_SPINLOCK_T task_state_tid);
|
||||
#endif
|
||||
|
||||
/* Flags the task <t> for immediate destruction and puts it into its first
|
||||
* thread's shared tasklet list if not yet queued/running. This will bypass
|
||||
* the priority scheduling and make the task show up as fast as possible in
|
||||
|
|
|
|||
Loading…
Reference in a new issue