Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:50

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  * Copyright (C) 2015, 2024 embedded brains GmbH & Co. KG
0005  *
0006  * Redistribution and use in source and binary forms, with or without
0007  * modification, are permitted provided that the following conditions
0008  * are met:
0009  * 1. Redistributions of source code must retain the above copyright
0010  *    notice, this list of conditions and the following disclaimer.
0011  * 2. Redistributions in binary form must reproduce the above copyright
0012  *    notice, this list of conditions and the following disclaimer in the
0013  *    documentation and/or other materials provided with the distribution.
0014  *
0015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0025  * POSSIBILITY OF SUCH DAMAGE.
0026  */
0027 
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031 
0032 #include "tmacros.h"
0033 
0034 #include <sys/lock.h>
0035 #include <inttypes.h>
0036 #include <pthread.h>
0037 #include <sched.h>
0038 #include <stdio.h>
0039 
0040 #include <rtems/test-info.h>
0041 
0042 const char rtems_test_name[] = "TMFINE 1";
0043 
0044 #if defined(RTEMS_SMP)
0045 #define CPU_COUNT 32
0046 #else
0047 #define CPU_COUNT 1
0048 #endif
0049 
0050 #define MSG_COUNT 3
0051 
0052 typedef struct {
0053   uint32_t value;
0054 } test_msg;
0055 
0056 typedef struct {
0057   rtems_test_parallel_context base;
0058   const char *test_sep;
0059   const char *counter_sep;
0060   rtems_id master;
0061   rtems_id sema;
0062   rtems_id mq[CPU_COUNT];
0063   uint32_t self_event_ops[CPU_COUNT][CPU_COUNT];
0064   uint32_t all_to_one_event_ops[CPU_COUNT][CPU_COUNT];
0065   uint32_t one_mutex_ops[CPU_COUNT][CPU_COUNT];
0066   uint32_t many_mutex_ops[CPU_COUNT][CPU_COUNT];
0067   uint32_t self_msg_ops[CPU_COUNT][CPU_COUNT];
0068   uint32_t many_to_one_msg_ops[CPU_COUNT][CPU_COUNT];
0069   uint32_t many_sys_lock_mutex_ops[CPU_COUNT][CPU_COUNT];
0070   uint32_t many_classic_ceiling_ops[CPU_COUNT][CPU_COUNT];
0071   uint32_t many_classic_mrsp_ops[CPU_COUNT][CPU_COUNT];
0072   uint32_t many_pthread_spinlock_ops[CPU_COUNT][CPU_COUNT];
0073   uint32_t many_pthread_mutex_inherit_ops[CPU_COUNT][CPU_COUNT];
0074   uint32_t many_pthread_mutex_protect_ops[CPU_COUNT][CPU_COUNT];
0075 } test_context;
0076 
0077 static test_context test_instance;
0078 
0079 static rtems_interval test_duration(void)
0080 {
0081   return rtems_clock_get_ticks_per_second();
0082 }
0083 
0084 static rtems_interval test_init(
0085   rtems_test_parallel_context *base,
0086   void *arg,
0087   size_t active_workers
0088 )
0089 {
0090   return test_duration();
0091 }
0092 
0093 static void test_fini(
0094   test_context *ctx,
0095   const char *type,
0096   const char *description,
0097   uint32_t *counters,
0098   size_t active_workers
0099 )
0100 {
0101   const char *value_sep;
0102   size_t i;
0103 
0104   if (active_workers == 1) {
0105     printf(
0106       "%s{\n"
0107       "    \"type\": \"%s\",\n"
0108       "    \"description\": \"%s\",\n"
0109       "    \"counter\": [",
0110       ctx->test_sep,
0111       type,
0112       description
0113     );
0114     ctx->test_sep = ", ";
0115     ctx->counter_sep = "\n      ";
0116   }
0117 
0118   printf("%s[", ctx->counter_sep);
0119   ctx->counter_sep = "],\n      ";
0120   value_sep = "";
0121 
0122   for (i = 0; i < active_workers; ++i) {
0123     printf(
0124       "%s%" PRIu32,
0125       value_sep,
0126       counters[i]
0127     );
0128     value_sep = ", ";
0129   }
0130 
0131   if (active_workers == rtems_scheduler_get_processor_maximum()) {
0132     printf("]\n    ]\n  }");
0133   }
0134 }
0135 
0136 static void test_self_event_body(
0137   rtems_test_parallel_context *base,
0138   void *arg,
0139   size_t active_workers,
0140   size_t worker_index
0141 )
0142 {
0143   test_context *ctx = (test_context *) base;
0144   rtems_id id = rtems_task_self();
0145   uint32_t counter = 0;
0146 
0147   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0148     rtems_status_code sc;
0149     rtems_event_set out;
0150 
0151     ++counter;
0152 
0153     sc = rtems_event_send(id, RTEMS_EVENT_0);
0154     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0155 
0156     sc = rtems_event_receive(
0157       RTEMS_EVENT_0,
0158       RTEMS_WAIT | RTEMS_EVENT_ANY,
0159       RTEMS_NO_TIMEOUT,
0160       &out
0161     );
0162     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0163   }
0164 
0165   ctx->self_event_ops[active_workers - 1][worker_index] = counter;
0166 }
0167 
0168 static void test_self_event_fini(
0169   rtems_test_parallel_context *base,
0170   void *arg,
0171   size_t active_workers
0172 )
0173 {
0174   test_context *ctx = (test_context *) base;
0175 
0176   test_fini(
0177     ctx,
0178     "event",
0179     "Send Event to Self",
0180     &ctx->self_event_ops[active_workers - 1][0],
0181     active_workers
0182   );
0183 }
0184 
0185 static void test_all_to_one_event_body(
0186   rtems_test_parallel_context *base,
0187   void *arg,
0188   size_t active_workers,
0189   size_t worker_index
0190 )
0191 {
0192   test_context *ctx = (test_context *) base;
0193   rtems_id id = rtems_task_self();
0194   bool is_master = rtems_test_parallel_is_master_worker(worker_index);
0195   uint32_t counter = 0;
0196 
0197   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0198     rtems_status_code sc;
0199 
0200     ++counter;
0201 
0202     sc = rtems_event_send(id, RTEMS_EVENT_0);
0203     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0204 
0205     if (is_master) {
0206       rtems_event_set out;
0207 
0208       sc = rtems_event_receive(
0209         RTEMS_ALL_EVENTS,
0210         RTEMS_WAIT | RTEMS_EVENT_ANY,
0211         RTEMS_NO_TIMEOUT,
0212         &out
0213       );
0214       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0215     }
0216   }
0217 
0218   ctx->all_to_one_event_ops[active_workers - 1][worker_index] = counter;
0219 }
0220 
0221 static void test_all_to_one_event_fini(
0222   rtems_test_parallel_context *base,
0223   void *arg,
0224   size_t active_workers
0225 )
0226 {
0227   test_context *ctx = (test_context *) base;
0228 
0229   test_fini(
0230     ctx,
0231     "event",
0232     "Send Event to One",
0233     &ctx->all_to_one_event_ops[active_workers - 1][0],
0234     active_workers
0235   );
0236 }
0237 
0238 static void test_one_mutex_body(
0239   rtems_test_parallel_context *base,
0240   void *arg,
0241   size_t active_workers,
0242   size_t worker_index
0243 )
0244 {
0245   test_context *ctx = (test_context *) base;
0246   rtems_id id = ctx->sema;
0247   uint32_t counter = 0;
0248 
0249   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0250     rtems_status_code sc;
0251 
0252     ++counter;
0253 
0254     sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0255     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0256 
0257     sc = rtems_semaphore_release(id);
0258     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0259   }
0260 
0261   ctx->one_mutex_ops[active_workers - 1][worker_index] = counter;
0262 }
0263 
0264 static void test_one_mutex_fini(
0265   rtems_test_parallel_context *base,
0266   void *arg,
0267   size_t active_workers
0268 )
0269 {
0270   test_context *ctx = (test_context *) base;
0271 
0272   test_fini(
0273     ctx,
0274     "contested-mutex",
0275     "Obtain/Release Contested Classic Inheritance Mutex",
0276     &ctx->one_mutex_ops[active_workers - 1][0],
0277     active_workers
0278   );
0279 }
0280 
0281 static void test_many_mutex_body(
0282   rtems_test_parallel_context *base,
0283   void *arg,
0284   size_t active_workers,
0285   size_t worker_index
0286 )
0287 {
0288   test_context *ctx = (test_context *) base;
0289   rtems_status_code sc;
0290   rtems_id id;
0291   uint32_t counter = 0;
0292 
0293   sc = rtems_semaphore_create(
0294     rtems_build_name('T', 'E', 'S', 'T'),
0295     1,
0296     RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
0297     0,
0298     &id
0299   );
0300   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0301 
0302   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0303     rtems_status_code sc;
0304 
0305     ++counter;
0306 
0307     sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0308     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0309 
0310     sc = rtems_semaphore_release(id);
0311     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0312   }
0313 
0314   ctx->many_mutex_ops[active_workers - 1][worker_index] = counter;
0315 
0316   sc = rtems_semaphore_delete(id);
0317   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0318 }
0319 
0320 static void test_many_mutex_fini(
0321   rtems_test_parallel_context *base,
0322   void *arg,
0323   size_t active_workers
0324 )
0325 {
0326   test_context *ctx = (test_context *) base;
0327 
0328   test_fini(
0329     ctx,
0330     "private-mutex",
0331     "Obtain/Release Private Classic Inheritance Mutex",
0332     &ctx->many_mutex_ops[active_workers - 1][0],
0333     active_workers
0334   );
0335 }
0336 
0337 static void test_self_msg_body(
0338   rtems_test_parallel_context *base,
0339   void *arg,
0340   size_t active_workers,
0341   size_t worker_index
0342 )
0343 {
0344   test_context *ctx = (test_context *) base;
0345   rtems_id id = ctx->mq[worker_index];
0346   uint32_t counter = 0;
0347 
0348   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0349     rtems_status_code sc;
0350     test_msg msg = { .value = 0 };
0351     size_t n;
0352 
0353     ++counter;
0354 
0355     sc = rtems_message_queue_send(id, &msg, sizeof(msg));
0356     rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_TOO_MANY);
0357 
0358     n = sizeof(msg);
0359     sc = rtems_message_queue_receive(
0360       id,
0361       &msg,
0362       &n,
0363       RTEMS_WAIT,
0364       RTEMS_NO_TIMEOUT
0365     );
0366     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0367     rtems_test_assert(n == sizeof(msg));
0368   }
0369 
0370   ctx->self_msg_ops[active_workers - 1][worker_index] = counter;
0371 }
0372 
0373 static void test_self_msg_fini(
0374   rtems_test_parallel_context *base,
0375   void *arg,
0376   size_t active_workers
0377 )
0378 {
0379   test_context *ctx = (test_context *) base;
0380 
0381   test_fini(
0382     ctx,
0383     "message",
0384     "Send Message to Self",
0385     &ctx->self_msg_ops[active_workers - 1][0],
0386     active_workers
0387   );
0388 }
0389 
0390 static void test_many_to_one_msg_body(
0391   rtems_test_parallel_context *base,
0392   void *arg,
0393   size_t active_workers,
0394   size_t worker_index
0395 )
0396 {
0397   test_context *ctx = (test_context *) base;
0398   rtems_id id = ctx->mq[0];
0399   bool is_master = rtems_test_parallel_is_master_worker(worker_index);
0400   uint32_t counter = 0;
0401 
0402   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0403     rtems_status_code sc;
0404     test_msg msg = { .value = 0 };
0405     size_t n;
0406 
0407     ++counter;
0408 
0409     sc = rtems_message_queue_send(id, &msg, sizeof(msg));
0410     rtems_test_assert(sc == RTEMS_SUCCESSFUL || sc == RTEMS_TOO_MANY);
0411 
0412     if (is_master) {
0413       n = sizeof(msg);
0414       sc = rtems_message_queue_receive(
0415         id,
0416         &msg,
0417         &n,
0418         RTEMS_WAIT,
0419         RTEMS_NO_TIMEOUT
0420       );
0421       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0422       rtems_test_assert(n == sizeof(msg));
0423     }
0424   }
0425 
0426   ctx->many_to_one_msg_ops[active_workers - 1][worker_index] = counter;
0427 }
0428 
0429 static void test_many_to_one_msg_fini(
0430   rtems_test_parallel_context *base,
0431   void *arg,
0432   size_t active_workers
0433 )
0434 {
0435   test_context *ctx = (test_context *) base;
0436 
0437   test_fini(
0438     ctx,
0439     "message",
0440     "Send Message to One Receiver",
0441     &ctx->many_to_one_msg_ops[active_workers - 1][0],
0442     active_workers
0443   );
0444 }
0445 
0446 static void test_many_sys_lock_mutex_body(
0447   rtems_test_parallel_context *base,
0448   void *arg,
0449   size_t active_workers,
0450   size_t worker_index
0451 )
0452 {
0453   test_context *ctx = (test_context *) base;
0454   struct _Mutex_Control mtx;
0455   uint32_t counter = 0;
0456 
0457   _Mutex_Initialize(&mtx);
0458 
0459   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0460     ++counter;
0461 
0462     _Mutex_Acquire(&mtx);
0463     _Mutex_Release(&mtx);
0464   }
0465 
0466   ctx->many_sys_lock_mutex_ops[active_workers - 1][worker_index] = counter;
0467 }
0468 
0469 static void test_many_sys_lock_mutex_fini(
0470   rtems_test_parallel_context *base,
0471   void *arg,
0472   size_t active_workers
0473 )
0474 {
0475   test_context *ctx = (test_context *) base;
0476 
0477   test_fini(
0478     ctx,
0479     "private-mutex",
0480     "Obtain/Release Private <sys/lock.h> Mutex",
0481     &ctx->many_sys_lock_mutex_ops[active_workers - 1][0],
0482     active_workers
0483   );
0484 }
0485 
0486 static void test_many_classic_ceiling_body(
0487   rtems_test_parallel_context *base,
0488   void *arg,
0489   size_t active_workers,
0490   size_t worker_index
0491 )
0492 {
0493   test_context *ctx = (test_context *) base;
0494   rtems_status_code sc;
0495   rtems_id id;
0496   uint32_t counter = 0;
0497 
0498   sc = rtems_semaphore_create(
0499     rtems_build_name('T', 'E', 'S', 'T'),
0500     1,
0501     RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY_CEILING | RTEMS_PRIORITY,
0502     1,
0503     &id
0504   );
0505   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0506 
0507   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0508     rtems_status_code sc;
0509 
0510     ++counter;
0511 
0512     sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0513     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0514 
0515     sc = rtems_semaphore_release(id);
0516     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0517   }
0518 
0519   ctx->many_classic_ceiling_ops[active_workers - 1][worker_index] = counter;
0520 
0521   sc = rtems_semaphore_delete(id);
0522   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0523 }
0524 
0525 static void test_many_classic_ceiling_fini(
0526   rtems_test_parallel_context *base,
0527   void *arg,
0528   size_t active_workers
0529 )
0530 {
0531   test_context *ctx = (test_context *) base;
0532 
0533   test_fini(
0534     ctx,
0535     "private-mutex",
0536     "Obtain/Release Private Classic Ceiling Mutex",
0537     &ctx->many_classic_ceiling_ops[active_workers - 1][0],
0538     active_workers
0539   );
0540 }
0541 
0542 static void test_many_classic_mrsp_body(
0543   rtems_test_parallel_context *base,
0544   void *arg,
0545   size_t active_workers,
0546   size_t worker_index
0547 )
0548 {
0549   test_context *ctx = (test_context *) base;
0550   rtems_status_code sc;
0551   rtems_id id;
0552   uint32_t counter = 0;
0553 
0554   sc = rtems_semaphore_create(
0555     rtems_build_name('T', 'E', 'S', 'T'),
0556     1,
0557     RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY |
0558       RTEMS_MULTIPROCESSOR_RESOURCE_SHARING,
0559     1,
0560     &id
0561   );
0562   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0563 
0564   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0565     rtems_status_code sc;
0566 
0567     ++counter;
0568 
0569     sc = rtems_semaphore_obtain(id, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0570     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0571 
0572     sc = rtems_semaphore_release(id);
0573     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0574   }
0575 
0576   ctx->many_classic_mrsp_ops[active_workers - 1][worker_index] = counter;
0577 
0578   sc = rtems_semaphore_delete(id);
0579   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0580 }
0581 
0582 static void test_many_classic_mrsp_fini(
0583   rtems_test_parallel_context *base,
0584   void *arg,
0585   size_t active_workers
0586 )
0587 {
0588   test_context *ctx = (test_context *) base;
0589 
0590   test_fini(
0591     ctx,
0592     "private-mutex",
0593     "Obtain/Release Private Classic MrsP Mutex",
0594     &ctx->many_classic_mrsp_ops[active_workers - 1][0],
0595     active_workers
0596   );
0597 }
0598 
0599 static void test_many_pthread_spinlock_body(
0600   rtems_test_parallel_context *base,
0601   void *arg,
0602   size_t active_workers,
0603   size_t worker_index
0604 )
0605 {
0606   test_context *ctx = (test_context *) base;
0607   int eno;
0608   pthread_spinlock_t spin;
0609   uint32_t counter = 0;
0610 
0611   eno = pthread_spin_init(&spin, 0);
0612   rtems_test_assert(eno == 0);
0613 
0614   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0615     ++counter;
0616 
0617     pthread_spin_lock(&spin);
0618     pthread_spin_unlock(&spin);
0619   }
0620 
0621   ctx->many_pthread_spinlock_ops[active_workers - 1][worker_index] = counter;
0622 
0623   eno = pthread_spin_destroy(&spin);
0624   rtems_test_assert(eno == 0);
0625 }
0626 
0627 static void test_many_pthread_spinlock_fini(
0628   rtems_test_parallel_context *base,
0629   void *arg,
0630   size_t active_workers
0631 )
0632 {
0633   test_context *ctx = (test_context *) base;
0634 
0635   test_fini(
0636     ctx,
0637     "private-mutex",
0638     "Obtain/Release Private Pthread Spinlock",
0639     &ctx->many_pthread_spinlock_ops[active_workers - 1][0],
0640     active_workers
0641   );
0642 }
0643 
0644 static void test_many_pthread_mutex_inherit_body(
0645   rtems_test_parallel_context *base,
0646   void *arg,
0647   size_t active_workers,
0648   size_t worker_index
0649 )
0650 {
0651   test_context *ctx = (test_context *) base;
0652   int eno;
0653   pthread_mutexattr_t attr;
0654   pthread_mutex_t mtx;
0655   uint32_t counter = 0;
0656 
0657   eno = pthread_mutexattr_init(&attr);
0658   rtems_test_assert(eno == 0);
0659 
0660   eno = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
0661   rtems_test_assert(eno == 0);
0662 
0663   eno = pthread_mutex_init(&mtx, &attr);
0664   rtems_test_assert(eno == 0);
0665 
0666   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0667     ++counter;
0668 
0669     pthread_mutex_lock(&mtx);
0670     pthread_mutex_unlock(&mtx);
0671   }
0672 
0673   ctx->many_pthread_mutex_inherit_ops[active_workers - 1][worker_index] =
0674     counter;
0675 
0676   eno = pthread_mutex_destroy(&mtx);
0677   rtems_test_assert(eno == 0);
0678 
0679   eno = pthread_mutexattr_destroy(&attr);
0680   rtems_test_assert(eno == 0);
0681 }
0682 
0683 static void test_many_pthread_mutex_inherit_fini(
0684   rtems_test_parallel_context *base,
0685   void *arg,
0686   size_t active_workers
0687 )
0688 {
0689   test_context *ctx = (test_context *) base;
0690 
0691   test_fini(
0692     ctx,
0693     "private-mutex",
0694     "Obtain/Release Private Pthread Inheritance Mutex",
0695     &ctx->many_pthread_mutex_inherit_ops[active_workers - 1][0],
0696     active_workers
0697   );
0698 }
0699 
0700 static void test_many_pthread_mutex_protect_body(
0701   rtems_test_parallel_context *base,
0702   void *arg,
0703   size_t active_workers,
0704   size_t worker_index
0705 )
0706 {
0707   test_context *ctx = (test_context *) base;
0708   int eno;
0709   pthread_mutexattr_t attr;
0710   pthread_mutex_t mtx;
0711   uint32_t counter = 0;
0712 
0713   eno = pthread_mutexattr_init(&attr);
0714   rtems_test_assert(eno == 0);
0715 
0716   eno = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_PROTECT);
0717   rtems_test_assert(eno == 0);
0718 
0719   eno = pthread_mutexattr_setprioceiling(
0720     &attr,
0721     sched_get_priority_max(SCHED_FIFO)
0722   );
0723   rtems_test_assert(eno == 0);
0724 
0725   eno = pthread_mutex_init(&mtx, &attr);
0726   rtems_test_assert(eno == 0);
0727 
0728   while (!rtems_test_parallel_stop_job(&ctx->base)) {
0729     ++counter;
0730 
0731     pthread_mutex_lock(&mtx);
0732     pthread_mutex_unlock(&mtx);
0733   }
0734 
0735   ctx->many_pthread_mutex_protect_ops[active_workers - 1][worker_index] =
0736     counter;
0737 
0738   eno = pthread_mutex_destroy(&mtx);
0739   rtems_test_assert(eno == 0);
0740 
0741   eno = pthread_mutexattr_destroy(&attr);
0742   rtems_test_assert(eno == 0);
0743 }
0744 
0745 static void test_many_pthread_mutex_protect_fini(
0746   rtems_test_parallel_context *base,
0747   void *arg,
0748   size_t active_workers
0749 )
0750 {
0751   test_context *ctx = (test_context *) base;
0752 
0753   test_fini(
0754     ctx,
0755     "private-mutex",
0756     "Obtain/Release Private Pthread Ceiling Mutex",
0757     &ctx->many_pthread_mutex_protect_ops[active_workers - 1][0],
0758     active_workers
0759   );
0760 }
0761 
0762 static const rtems_test_parallel_job test_jobs[] = {
0763   {
0764     .init = test_init,
0765     .body = test_self_event_body,
0766     .fini = test_self_event_fini,
0767     .cascade = true
0768   }, {
0769     .init = test_init,
0770     .body = test_all_to_one_event_body,
0771     .fini = test_all_to_one_event_fini,
0772     .cascade = true
0773   }, {
0774     .init = test_init,
0775     .body = test_one_mutex_body,
0776     .fini = test_one_mutex_fini,
0777     .cascade = true
0778   }, {
0779     .init = test_init,
0780     .body = test_self_msg_body,
0781     .fini = test_self_msg_fini,
0782     .cascade = true
0783   }, {
0784     .init = test_init,
0785     .body = test_many_to_one_msg_body,
0786     .fini = test_many_to_one_msg_fini,
0787     .cascade = true
0788   }, {
0789     .init = test_init,
0790     .body = test_many_pthread_spinlock_body,
0791     .fini = test_many_pthread_spinlock_fini,
0792     .cascade = true
0793   }, {
0794     .init = test_init,
0795     .body = test_many_sys_lock_mutex_body,
0796     .fini = test_many_sys_lock_mutex_fini,
0797     .cascade = true
0798   }, {
0799     .init = test_init,
0800     .body = test_many_pthread_mutex_inherit_body,
0801     .fini = test_many_pthread_mutex_inherit_fini,
0802     .cascade = true
0803   }, {
0804     .init = test_init,
0805     .body = test_many_mutex_body,
0806     .fini = test_many_mutex_fini,
0807     .cascade = true
0808   }, {
0809     .init = test_init,
0810     .body = test_many_pthread_mutex_protect_body,
0811     .fini = test_many_pthread_mutex_protect_fini,
0812     .cascade = true
0813   }, {
0814     .init = test_init,
0815     .body = test_many_classic_ceiling_body,
0816     .fini = test_many_classic_ceiling_fini,
0817     .cascade = true
0818   }, {
0819     .init = test_init,
0820     .body = test_many_classic_mrsp_body,
0821     .fini = test_many_classic_mrsp_fini,
0822     .cascade = true
0823   }
0824 };
0825 
0826 static void Init(rtems_task_argument arg)
0827 {
0828   test_context *ctx = &test_instance;
0829   rtems_status_code sc;
0830   size_t i;
0831 
0832   TEST_BEGIN();
0833 
0834   ctx->master = rtems_task_self();
0835 
0836   sc = rtems_semaphore_create(
0837     rtems_build_name('T', 'E', 'S', 'T'),
0838     1,
0839     RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
0840     0,
0841     &ctx->sema
0842   );
0843   rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0844 
0845   for (i = 0; i < CPU_COUNT; ++i) {
0846     sc = rtems_message_queue_create(
0847       rtems_build_name('T', 'E', 'S', 'T'),
0848       MSG_COUNT,
0849       sizeof(test_msg),
0850       RTEMS_DEFAULT_ATTRIBUTES,
0851       &ctx->mq[i]
0852     );
0853     rtems_test_assert(sc == RTEMS_SUCCESSFUL);
0854   }
0855 
0856   printf("*** BEGIN OF JSON DATA ***\n[\n  ");
0857 
0858   ctx->test_sep = "";
0859   rtems_test_parallel(
0860     &ctx->base,
0861     NULL,
0862     &test_jobs[0],
0863     RTEMS_ARRAY_SIZE(test_jobs)
0864   );
0865 
0866   printf("\n]\n*** END OF JSON DATA ***\n");
0867 
0868   TEST_END();
0869   rtems_test_exit(0);
0870 }
0871 
0872 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0873 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
0874 
0875 #define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
0876 
0877 #define CONFIGURE_MAXIMUM_TIMERS 1
0878 
0879 #define CONFIGURE_MAXIMUM_SEMAPHORES (1 + CPU_COUNT)
0880 
0881 #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES CPU_COUNT
0882 
0883 #define CONFIGURE_MESSAGE_BUFFER_MEMORY \
0884   CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(MSG_COUNT, sizeof(test_msg))
0885 
0886 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0887 
0888 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0889 
0890 #define CONFIGURE_INIT_TASK_PRIORITY 2
0891 
0892 #define CONFIGURE_MAXIMUM_PROCESSORS CPU_COUNT
0893 
0894 #define CONFIGURE_INIT
0895 
0896 #include <rtems/confdefs.h>