/**************************************************************************** * apps/testing/ostest/wqueue.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #if defined(CONFIG_SCHED_LPWORK) || defined(CONFIG_SCHED_HPWORK) /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define SLEEP_TIME (100 * 1000) #define TEST_COUNT (100) #define VERIFY_COUNT (100) #ifdef CONFIG_SCHED_LPWORK # define TEST_QUEUE LPWORK # define TEST_QUEUE_PRIORITY CONFIG_SCHED_LPWORKPRIORITY #else # define TEST_QUEUE HPWORK # define TEST_QUEUE_PRIORITY CONFIG_SCHED_HPWORKPRIORITY #endif /**************************************************************************** * Private Functions ****************************************************************************/ static void empty_worker(FAR void *arg) { } static void sleep_worker(FAR void *arg) { FAR sem_t *sem = arg; usleep(SLEEP_TIME); sem_post(sem); } static void count_worker(FAR void *arg) { FAR sem_t *sem = arg; sem_post(sem); } static FAR void *tester(FAR void *arg) { int interval = (intptr_t)arg; int i; struct work_s work; memset(&work, 0, sizeof(work)); for (i = 0; i < TEST_COUNT; i++) { work_queue(TEST_QUEUE, &work, empty_worker, NULL, 0); work_cancel(TEST_QUEUE, &work); usleep(interval); } usleep(SLEEP_TIME); /* Wait for workers to run. */ return NULL; } static FAR void *verifier(FAR void *arg) { sem_t sem; sem_t call_sem; int call_count; int i; struct work_s work[VERIFY_COUNT + 1]; sem_init(&sem, 0, 0); sem_init(&call_sem, 0, 0); memset(&work, 0, sizeof(work)); /* Queue sleep worker. */ work_queue(TEST_QUEUE, &work[0], sleep_worker, &sem, 0); /* Queue count workers when TEST_QUEUE is busy. */ for (i = 1; i <= VERIFY_COUNT; i++) { work_queue(TEST_QUEUE, &work[i], count_worker, &call_sem, 0); } /* Wait for sleep worker to run. */ sem_wait(&sem); /* Wait for count workers to run. */ do { usleep(SLEEP_TIME); sem_getvalue(&call_sem, &call_count); } while (call_count != VERIFY_COUNT); sem_getvalue(&call_sem, &call_count); printf("wqueue_test: call = %d, expect = %d\n", call_count, VERIFY_COUNT); for (i = 0; i < VERIFY_COUNT; i++) { ASSERT(work[i].worker == NULL); } ASSERT(call_count == VERIFY_COUNT); return NULL; } static void run_once(int interval, int priority_test, int priority_verify) { pthread_t thread; pthread_attr_t attr; struct sched_param sparam; pthread_attr_init(&attr); memset(&sparam, 0, sizeof(sparam)); /* Tester: try race conditions. */ sparam.sched_priority = priority_test; pthread_attr_setschedparam(&attr, &sparam); pthread_create(&thread, &attr, tester, (FAR void *)(intptr_t)interval); pthread_join(thread, NULL); /* Verifier: make sure queue is still working properly. */ sparam.sched_priority = priority_verify; pthread_attr_setschedparam(&attr, &sparam); pthread_attr_setstacksize(&attr, VERIFY_COUNT * sizeof(struct work_s) + CONFIG_PTHREAD_STACK_DEFAULT); pthread_create(&thread, &attr, verifier, NULL); pthread_join(thread, NULL); } /**************************************************************************** * Public Functions ****************************************************************************/ void wqueue_test(void) { int interval; int priority_test; int priority_verify; for (interval = 0; interval <= 1; interval++) { for (priority_test = TEST_QUEUE_PRIORITY - 1; priority_test <= TEST_QUEUE_PRIORITY + 1; priority_test++) { for (priority_verify = TEST_QUEUE_PRIORITY - 1; priority_verify <= TEST_QUEUE_PRIORITY + 1; priority_verify++) { run_once(interval, priority_test, priority_verify); } } } } #endif /* CONFIG_SCHED_LPWORK || CONFIG_SCHED_HPWORK */