Add test for verifying SMP operation
This commit is contained in:
parent
65a1d53079
commit
65a6739593
@ -1554,4 +1554,5 @@
|
|||||||
(2016-02-19).
|
(2016-02-19).
|
||||||
* apps/examples/leds: An example to demonstrate use of LED
|
* apps/examples/leds: An example to demonstrate use of LED
|
||||||
driver (2016-02-20).
|
driver (2016-02-20).
|
||||||
|
* apps/examples/smp: An verifying SMP configurations (2016-02-21).
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ source "$APPSDIR/examples/slcd/Kconfig"
|
|||||||
source "$APPSDIR/examples/flash_test/Kconfig"
|
source "$APPSDIR/examples/flash_test/Kconfig"
|
||||||
source "$APPSDIR/examples/smart_test/Kconfig"
|
source "$APPSDIR/examples/smart_test/Kconfig"
|
||||||
source "$APPSDIR/examples/smart/Kconfig"
|
source "$APPSDIR/examples/smart/Kconfig"
|
||||||
|
source "$APPSDIR/examples/smp/Kconfig"
|
||||||
source "$APPSDIR/examples/tcpecho/Kconfig"
|
source "$APPSDIR/examples/tcpecho/Kconfig"
|
||||||
source "$APPSDIR/examples/telnetd/Kconfig"
|
source "$APPSDIR/examples/telnetd/Kconfig"
|
||||||
source "$APPSDIR/examples/thttpd/Kconfig"
|
source "$APPSDIR/examples/thttpd/Kconfig"
|
||||||
|
@ -1829,6 +1829,12 @@ examples/smart_test
|
|||||||
* CONFIG_NSH_BUILTIN_APPS=y: This test can be built only as an NSH
|
* CONFIG_NSH_BUILTIN_APPS=y: This test can be built only as an NSH
|
||||||
command
|
command
|
||||||
|
|
||||||
|
examples/smp
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
This is a simple test for SMP functionality. It is basically just the
|
||||||
|
pthread barrier test with some custom instrumentation.
|
||||||
|
|
||||||
examples/tcpecho
|
examples/tcpecho
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
11
examples/smp/.gitignore
vendored
Normal file
11
examples/smp/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/Make.dep
|
||||||
|
/.depend
|
||||||
|
/.built
|
||||||
|
/*.asm
|
||||||
|
/*.obj
|
||||||
|
/*.rel
|
||||||
|
/*.lst
|
||||||
|
/*.sym
|
||||||
|
/*.adb
|
||||||
|
/*.lib
|
||||||
|
/*.src
|
40
examples/smp/Kconfig
Normal file
40
examples/smp/Kconfig
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# For a description of the syntax of this configuration file,
|
||||||
|
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||||
|
#
|
||||||
|
|
||||||
|
config EXAMPLES_SMP
|
||||||
|
bool "SMP example"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enable the SMP example. This example basically extracts the pthread
|
||||||
|
barrier test from apps/examples/ostest and adds some instrumentation
|
||||||
|
useful for debugging SMP implementations.
|
||||||
|
|
||||||
|
if EXAMPLES_SMP
|
||||||
|
|
||||||
|
config EXAMPLES_SMP_NBARRIER_THREADS
|
||||||
|
int "Number of barrier threads"
|
||||||
|
default 8
|
||||||
|
---help---
|
||||||
|
Specifies the number of threads to create in the SMP test. The default
|
||||||
|
is 8 but a smaller number may be needed on systems without sufficient memory
|
||||||
|
to start so many threads.
|
||||||
|
|
||||||
|
config EXAMPLES_SMP_PROGNAME
|
||||||
|
string "Program name"
|
||||||
|
default "smp"
|
||||||
|
depends on BUILD_KERNEL
|
||||||
|
---help---
|
||||||
|
This is the name of the program that will be use when the NSH ELF
|
||||||
|
program is installed.
|
||||||
|
|
||||||
|
config EXAMPLES_SMP_PRIORITY
|
||||||
|
int "SMP task priority"
|
||||||
|
default 100
|
||||||
|
|
||||||
|
config EXAMPLES_SMP_STACKSIZE
|
||||||
|
int "SMP stack size"
|
||||||
|
default 2048
|
||||||
|
|
||||||
|
endif
|
39
examples/smp/Make.defs
Normal file
39
examples/smp/Make.defs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
############################################################################
|
||||||
|
# apps/examples/smp/Make.defs
|
||||||
|
# Adds selected applications to apps/ build
|
||||||
|
#
|
||||||
|
# Copyright (C) 2016 Gregory Nutt. All rights reserved.
|
||||||
|
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
# used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_EXAMPLES_HELLO),y)
|
||||||
|
CONFIGURED_APPS += examples/smp
|
||||||
|
endif
|
56
examples/smp/Makefile
Normal file
56
examples/smp/Makefile
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
############################################################################
|
||||||
|
# apps/examples/smp/Makefile
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008, 2010-2013 Gregory Nutt. All rights reserved.
|
||||||
|
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
# used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
-include $(TOPDIR)/Make.defs
|
||||||
|
|
||||||
|
# SMP built-in application info
|
||||||
|
|
||||||
|
CONFIG_EXAMPLES_SMP_PRIORITY ?= SCHED_PRIORITY_DEFAULT
|
||||||
|
CONFIG_EXAMPLES_SMP_STACKSIZE ?= 2048
|
||||||
|
|
||||||
|
APPNAME = smp
|
||||||
|
PRIORITY = $(CONFIG_EXAMPLES_SMP_PRIORITY)
|
||||||
|
STACKSIZE = $(CONFIG_EXAMPLES_SMP_STACKSIZE)
|
||||||
|
|
||||||
|
# SMP Example
|
||||||
|
|
||||||
|
ASRCS =
|
||||||
|
CSRCS =
|
||||||
|
MAINSRC = smp_main.c
|
||||||
|
|
||||||
|
CONFIG_EXAMPLES_SMP_PROGNAME ?= smp$(EXEEXT)
|
||||||
|
PROGNAME = $(CONFIG_EXAMPLES_SMP_PROGNAME)
|
||||||
|
|
||||||
|
include $(APPDIR)/Application.mk
|
341
examples/smp/smp_main.c
Normal file
341
examples/smp/smp_main.c
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* examples/smp/smp_main.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define HOG_MSEC 1000
|
||||||
|
#define YIELD_MSEC 100
|
||||||
|
#define IMPOSSIBLE_CPU -1
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static pthread_barrier_t g_smp_barrier;
|
||||||
|
|
||||||
|
#if defined(CONFIG_SMP) && defined(CONFIG_BUILD_FLAT)
|
||||||
|
static volatile int g_thread_cpu[CONFIG_EXAMPLES_SMP_NBARRIER_THREADS+1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: show_cpu / show_cpu_conditional
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This depends on internal OS interfaces that are not generally available
|
||||||
|
* but can be accessed (albeit inappropriatley) in a FLAT build
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_SMP) && defined(CONFIG_BUILD_FLAT)
|
||||||
|
int up_cpu_index(void);
|
||||||
|
|
||||||
|
static void show_cpu(FAR const char *caller, int threadno)
|
||||||
|
{
|
||||||
|
g_thread_cpu[threadno] = up_cpu_index();
|
||||||
|
printf("%s[%d]: Running on CPU%d\n", caller, threadno, g_thread_cpu[threadno]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_cpu_conditional(FAR const char *caller, int threadno)
|
||||||
|
{
|
||||||
|
int cpu = up_cpu_index();
|
||||||
|
|
||||||
|
if (cpu != g_thread_cpu[threadno])
|
||||||
|
{
|
||||||
|
g_thread_cpu[threadno] = cpu;
|
||||||
|
printf("%s[%d]: Now running on CPU%d\n", caller, threadno, cpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define show_cpu(c)
|
||||||
|
# define show_cpu_conditional(c)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: hog_milliseconds
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Delay inline for the specified number of milliseconds.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void hog_milliseconds(unsigned int milliseconds)
|
||||||
|
{
|
||||||
|
volatile unsigned int i;
|
||||||
|
volatile unsigned int j;
|
||||||
|
|
||||||
|
for (i = 0; i < milliseconds; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < CONFIG_BOARD_LOOPSPERMSEC; j++)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: hog_time
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Delay for awhile, calling pthread_yield() now and then to allow other
|
||||||
|
* pthreads to get CPU time.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void hog_time(FAR const char *caller, int threadno)
|
||||||
|
{
|
||||||
|
unsigned int remaining = HOG_MSEC;
|
||||||
|
unsigned int hogmsec;
|
||||||
|
|
||||||
|
while (remaining > 0)
|
||||||
|
{
|
||||||
|
/* Hog some CPU */
|
||||||
|
|
||||||
|
hogmsec = YIELD_MSEC;
|
||||||
|
if (hogmsec > remaining)
|
||||||
|
{
|
||||||
|
hogmsec = remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
hog_milliseconds(hogmsec);
|
||||||
|
remaining -= hogmsec;
|
||||||
|
|
||||||
|
/* Let other threads run */
|
||||||
|
|
||||||
|
(void)pthread_yield();
|
||||||
|
show_cpu_conditional(caller, threadno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: barrier_thread
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static pthread_addr_t barrier_thread(pthread_addr_t parameter)
|
||||||
|
{
|
||||||
|
int threadno = (int)((intptr_t)parameter);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
printf("Thread[%d]: Started\n", threadno);
|
||||||
|
show_cpu("Thread", threadno);
|
||||||
|
|
||||||
|
/* Hog some CPU time */
|
||||||
|
|
||||||
|
hog_time("Thread", threadno);
|
||||||
|
|
||||||
|
/* Wait at the barrier until all threads are synchronized. */
|
||||||
|
|
||||||
|
printf("Thread[%d]: Calling pthread_barrier_wait()\n",
|
||||||
|
threadno);
|
||||||
|
fflush(stdout);
|
||||||
|
show_cpu_conditional("Thread", threadno);
|
||||||
|
|
||||||
|
ret = pthread_barrier_wait(&g_smp_barrier);
|
||||||
|
if (ret == 0)
|
||||||
|
{
|
||||||
|
printf("Thread[%d]: Back with ret=0 (I am not special)\n",
|
||||||
|
threadno);
|
||||||
|
}
|
||||||
|
else if (ret == PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
|
{
|
||||||
|
printf("Thread[%d]: Back with "
|
||||||
|
"ret=PTHREAD_BARRIER_SERIAL_THREAD (I AM SPECIAL)\n",
|
||||||
|
threadno);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Thread[%d]: ERROR could not get semaphore value\n",
|
||||||
|
threadno);
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
show_cpu_conditional("Thread", threadno);
|
||||||
|
|
||||||
|
/* Hog some more CPU time */
|
||||||
|
|
||||||
|
hog_time("Thread", threadno);
|
||||||
|
|
||||||
|
/* Then exit */
|
||||||
|
|
||||||
|
printf("Thread[%d]: Done\n", threadno);
|
||||||
|
fflush(stdout);
|
||||||
|
show_cpu_conditional("Thread", threadno);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* smp_main
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
|
int main(int argc, FAR char *argv[])
|
||||||
|
#else
|
||||||
|
int smp_main(int argc, char *argv[])
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
pthread_t threadid[CONFIG_EXAMPLES_SMP_NBARRIER_THREADS];
|
||||||
|
pthread_addr_t result;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_barrierattr_t barrierattr;
|
||||||
|
int errcode = EXIT_SUCCESS;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
show_cpu(" Main", 0);
|
||||||
|
printf(" Main[0]: Initializing barrier\n");
|
||||||
|
|
||||||
|
ret = pthread_barrierattr_init(&barrierattr);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
printf(" Main[0]: pthread_barrierattr_init failed, ret=%d\n", ret);
|
||||||
|
|
||||||
|
errcode = EXIT_FAILURE;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pthread_barrier_init(&g_smp_barrier, &barrierattr,
|
||||||
|
CONFIG_EXAMPLES_SMP_NBARRIER_THREADS);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
printf(" Main[0]: pthread_barrierattr_init failed, ret=%d\n", ret);
|
||||||
|
|
||||||
|
errcode = EXIT_FAILURE;
|
||||||
|
goto errout_with_attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the barrier */
|
||||||
|
|
||||||
|
(void)pthread_barrierattr_init(&barrierattr);
|
||||||
|
|
||||||
|
/* Start CONFIG_EXAMPLES_SMP_NBARRIER_THREADS thread instances */
|
||||||
|
|
||||||
|
ret = pthread_attr_init(&attr);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
printf(" Main[0]: pthread_attr_init failed, ret=%d\n", ret);
|
||||||
|
|
||||||
|
errcode = EXIT_FAILURE;
|
||||||
|
goto errout_with_barrier;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(threadid, 0, sizeof(pthread_t) * CONFIG_EXAMPLES_SMP_NBARRIER_THREADS);
|
||||||
|
for (i = 0; i < CONFIG_EXAMPLES_SMP_NBARRIER_THREADS; i++)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_SMP) && defined(CONFIG_BUILD_FLAT)
|
||||||
|
g_thread_cpu[i] = IMPOSSIBLE_CPU;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = pthread_create(&threadid[i], &attr, barrier_thread,
|
||||||
|
(pthread_addr_t)((uintptr_t)i+1));
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
printf(" Main[0]: Error in thread %d create, ret=%d\n", i+1, ret);
|
||||||
|
printf(" Main[0]: Test aborted with waiting threads\n");
|
||||||
|
|
||||||
|
errcode = EXIT_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" Main[0]: Thread %d created\n", i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
show_cpu_conditional(" Main", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
show_cpu_conditional(" Main", 0);
|
||||||
|
|
||||||
|
/* Wait for all thread instances to complete */
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_EXAMPLES_SMP_NBARRIER_THREADS; i++)
|
||||||
|
{
|
||||||
|
if (threadid[i] != 0);
|
||||||
|
{
|
||||||
|
ret = pthread_join(threadid[i], &result);
|
||||||
|
show_cpu_conditional(" Main", 0);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
printf(" Main[0]: Error in thread %d join, ret=%d\n", i+1, ret);
|
||||||
|
errcode = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" Main[0]: Thread %d completed with result=%p\n", i+1, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy the barrier */
|
||||||
|
|
||||||
|
errout_with_barrier:
|
||||||
|
ret = pthread_barrier_destroy(&g_smp_barrier);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
printf(" Main[0]: pthread_barrier_destroy failed, ret=%d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
errout_with_attr:
|
||||||
|
ret = pthread_barrierattr_destroy(&barrierattr);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
printf(" Main[0]: pthread_barrierattr_destroy failed, ret=%d\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
fflush(stdout);
|
||||||
|
show_cpu_conditional(" Main", 0);
|
||||||
|
return errcode;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user