From c63e8bbeb9ec2fac31a88821112076c50321b292 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 19 Apr 2019 11:02:02 +0200 Subject: score: Modify _Per_CPU_Perform_jobs() Process only the jobs initially registered on the processing list. This makes it possible to add jobs for the current processor in a job handler. These jobs are processed with the next SMP_MESSAGE_PERFORM_JOBS message. The lock is only acquired and released once. --- cpukit/score/src/smpmulticastaction.c | 12 +++++---- testsuites/smptests/smpmulticast01/init.c | 41 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/cpukit/score/src/smpmulticastaction.c b/cpukit/score/src/smpmulticastaction.c index 1207000e6a..b5d21a4b56 100644 --- a/cpukit/score/src/smpmulticastaction.c +++ b/cpukit/score/src/smpmulticastaction.c @@ -44,18 +44,20 @@ void _Per_CPU_Perform_jobs( Per_CPU_Control *cpu ) Per_CPU_Job *job; _Per_CPU_Jobs_ISR_disable_and_acquire( cpu, &lock_context ); + job = cpu->Jobs.head; + cpu->Jobs.head = NULL; + _Per_CPU_Jobs_release_and_ISR_enable( cpu, &lock_context ); - while ( ( job = cpu->Jobs.head ) != NULL ) { + while ( job != NULL ) { const Per_CPU_Job_context *context; - - cpu->Jobs.head = job->next; - _Per_CPU_Jobs_release_and_ISR_enable( cpu, &lock_context ); + Per_CPU_Job *next; context = job->context; + next = job->next; ( *context->handler )( context->arg ); _Atomic_Store_ulong( &job->done, PER_CPU_JOB_DONE, ATOMIC_ORDER_RELEASE ); - _Per_CPU_Jobs_ISR_disable_and_acquire( cpu, &lock_context ); + job = next; } } diff --git a/testsuites/smptests/smpmulticast01/init.c b/testsuites/smptests/smpmulticast01/init.c index 9e5d15f795..e7c533027f 100644 --- a/testsuites/smptests/smpmulticast01/init.c +++ b/testsuites/smptests/smpmulticast01/init.c @@ -394,6 +394,47 @@ T_TEST_CASE(JobOrder) _Thread_Dispatch_enable(cpu_self); } +#define TEST_ADD_JOB_IN_JOB_JOBS 3 + +static Per_CPU_Job add_job_in_job_jobs[TEST_ADD_JOB_IN_JOB_JOBS]; + +static void add_job_in_job_handler_0(void *arg) +{ + T_step(1, "invalid job order"); + _Per_CPU_Add_job(_Per_CPU_Get(), &add_job_in_job_jobs[1]); +} + +static void add_job_in_job_handler_1(void *arg) +{ + T_step(3, "invalid job order"); +} + +static const Per_CPU_Job_context +add_job_in_job_contexts[TEST_ADD_JOB_IN_JOB_JOBS] = { + { .handler = add_job_in_job_handler_0 }, + { .handler = add_job_in_job_handler_1 } +}; + +T_TEST_CASE(AddJobInJob) +{ + Per_CPU_Control *cpu_self; + size_t i; + + T_plan(4); + cpu_self = _Thread_Dispatch_disable(); + + for (i = 0; i < TEST_ADD_JOB_IN_JOB_JOBS; ++i) { + add_job_in_job_jobs[i].context = &add_job_in_job_contexts[i]; + } + + _Per_CPU_Add_job(cpu_self, &add_job_in_job_jobs[0]); + T_step(0, "wrong job processing time"); + _SMP_Send_message(_Per_CPU_Get_index(cpu_self), SMP_MESSAGE_PERFORM_JOBS); + T_step(2, "wrong job processing time"); + _SMP_Send_message(_Per_CPU_Get_index(cpu_self), SMP_MESSAGE_PERFORM_JOBS); + _Thread_Dispatch_enable(cpu_self); +} + T_TEST_CASE(UnicastDuringMultitaskingIRQDisabled) { test_unicast(&test_instance, multicast_action_irq_disabled); -- cgit v1.2.3