CELIX-272: Added locking/threading example to test synchronization solutions and isues. Introduced release/retain concept for service reference and service registration.
Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/e0231e51 Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/e0231e51 Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/e0231e51 Branch: refs/heads/feature/CELIX-272_synchronization_service_registry Commit: e0231e51e4cac30018c7a71f9469e838348f642b Parents: e9f2baa Author: Pepijn Noltes <[email protected]> Authored: Mon Nov 9 18:06:18 2015 +0100 Committer: Pepijn Noltes <[email protected]> Committed: Mon Nov 9 18:06:18 2015 +0100 ---------------------------------------------------------------------- .../private/src/dm_component_impl.c | 5 +- examples/CMakeLists.txt | 1 + examples/deploy.cmake | 3 + examples/locking/CMakeLists.txt | 24 ++ examples/locking/benchmark/CMakeLists.txt | 30 ++ .../private/src/benchmark_runner_activator.c | 255 +++++++++++++ .../benchmark/public/include/benchmark.h | 29 ++ .../benchmark/public/include/benchmark_result.h | 20 + .../public/include/benchmark_service.h | 27 ++ .../public/include/frequency_service.h | 47 +++ .../benchmark/public/include/math_service.h | 40 ++ .../benchmark/public/src/benchmark_activator.c | 133 +++++++ examples/locking/consumer.c | 372 +++++++++++++++++++ examples/locking/math_provider/CMakeLists.txt | 32 ++ .../private/include/math_component.h | 14 + .../math_provider/private/src/math_component.c | 28 ++ .../private/src/provider_activator.c | 219 +++++++++++ .../modified_bool_benchmark/CMakeLists.txt | 32 ++ .../private/src/modified_bool_benchmark.c | 162 ++++++++ examples/locking/mutex_benchmark/CMakeLists.txt | 32 ++ .../private/src/mutex_benchmark.c | 117 ++++++ .../locking/reference_benchmark/CMakeLists.txt | 32 ++ .../private/src/reference_benchmark.c | 116 ++++++ .../locking/start_stop_benchmark/CMakeLists.txt | 32 ++ .../private/src/start_stop_benchmark.c | 189 ++++++++++ .../private/include/service_reference_private.h | 9 +- .../include/service_registration_private.h | 6 +- .../private/include/service_registry_private.h | 1 + framework/private/src/properties.c | 22 ++ framework/private/src/service_reference.c | 71 ++-- framework/private/src/service_registration.c | 71 ++-- framework/private/src/service_registry.c | 26 +- framework/public/include/properties.h | 3 + 33 files changed, 2130 insertions(+), 70 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/dependency_manager/private/src/dm_component_impl.c ---------------------------------------------------------------------- diff --git a/dependency_manager/private/src/dm_component_impl.c b/dependency_manager/private/src/dm_component_impl.c index d08bc28..aa34389 100644 --- a/dependency_manager/private/src/dm_component_impl.c +++ b/dependency_manager/private/src/dm_component_impl.c @@ -1097,8 +1097,9 @@ celix_status_t component_registerServices(dm_component_pt component) { for (i = 0; i < arrayList_size(component->dm_interfaces); i++) { dm_interface_t *interface = arrayList_get(component->dm_interfaces, i); - - bundleContext_registerService(component->context, interface->serviceName, interface->service, interface->properties, &interface->registration); + properties_pt regProps = NULL; + properties_copy(interface->properties, ®Props); + bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps, &interface->registration); } } http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 677a6aa..55468a4 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -32,6 +32,7 @@ if (EXAMPLES) add_subdirectory(osgi-in-action/chapter04-correct-listener) add_subdirectory(osgi-in-action/chapter01-greeting-example) #add_subdirectory(osgi-in-action/chapter04-paint-example) chapter4 example is still based on APR + add_subdirectory(locking) #add_subdirectory(embedding) embedding is still baed on APR endif(EXAMPLES) http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/deploy.cmake ---------------------------------------------------------------------- diff --git a/examples/deploy.cmake b/examples/deploy.cmake index 24c7a11..234f90b 100644 --- a/examples/deploy.cmake +++ b/examples/deploy.cmake @@ -28,4 +28,7 @@ if (EXAMPLES) if (NOT ANDROID) deploy("mongoose" BUNDLES shell shell_tui log_service apache_celix_examples_mongoose) endif () + + deploy("locking_example" BUNDLES benchmark_runner reference_benchmark start_stop_benchmark mutex_benchmark math_provider shell shell_tui log_service log_writer) + endif (EXAMPLES) http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/locking/CMakeLists.txt b/examples/locking/CMakeLists.txt new file mode 100644 index 0000000..e6c80ab --- /dev/null +++ b/examples/locking/CMakeLists.txt @@ -0,0 +1,24 @@ + # 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. + +add_subdirectory(benchmark) +add_subdirectory(math_provider) + +add_subdirectory(mutex_benchmark) +add_subdirectory(reference_benchmark) +add_subdirectory(start_stop_benchmark) +add_subdirectory(modified_bool_benchmark) http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/CMakeLists.txt b/examples/locking/benchmark/CMakeLists.txt new file mode 100644 index 0000000..ce5db7c --- /dev/null +++ b/examples/locking/benchmark/CMakeLists.txt @@ -0,0 +1,30 @@ +# 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. + +SET(BUNDLE_SYMBOLICNAME benchmark_runner) +SET(BUNDLE_VERSION 0.0.0) + +bundle(benchmark_runner SOURCES + private/src/benchmark_runner_activator +) + +include_directories(private/include) +include_directories(public/include) +include_directories(${PROJECT_SOURCE_DIR}/framework/public/include) +include_directories(${PROJECT_SOURCE_DIR}/utils/public/include) + +target_link_libraries(benchmark_runner celix_framework) http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/private/src/benchmark_runner_activator.c ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/private/src/benchmark_runner_activator.c b/examples/locking/benchmark/private/src/benchmark_runner_activator.c new file mode 100644 index 0000000..e06b77b --- /dev/null +++ b/examples/locking/benchmark/private/src/benchmark_runner_activator.c @@ -0,0 +1,255 @@ +/** + *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. + */ +/* + * benchmark_activator.c + * + * \date Feb 12, 2014 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + + + +#include <stdlib.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/queue.h> + +#include <pthread.h> + +#include "bundle_activator.h" +#include "bundle_context.h" +#include "service_registration.h" +#include "service_tracker.h" + +#include "benchmark_service.h" +#include "frequency_service.h" + +static celix_status_t benchmarkRunner_addingService(void * handle, service_reference_pt reference, void **service); +static celix_status_t benchmarkRunner_addedService(void * handle, service_reference_pt reference, void * service); +static celix_status_t benchmarkRunner_modifiedService(void * handle, service_reference_pt reference, void * service); +static celix_status_t benchmarkRunner_removedService(void * handle, service_reference_pt reference, void * service); + +static void benchmarkRunner_runBenchmark(struct activator *activator); +static void benchmarkRunner_printHeader(char *name, unsigned int nrOfSamples); +static void benchmarkRunner_printResult(benchmark_result_t result, double updateFreq, unsigned long elapsedTime); +static void benchmarkRunner_printFooter(char *name); + +struct benchmark_entry { + benchmark_service_pt benchmark; + LIST_ENTRY(benchmark_entry) entries; +}; + +struct activator { + bundle_context_pt context; + service_tracker_customizer_pt customizer; + service_tracker_pt tracker; + pthread_t thread; + + pthread_mutex_t mutex; + array_list_pt benchmarks; + LIST_HEAD(benchmark_entries, entries) benchmarkEntries; + frequency_service_pt freqService; +}; + +celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { + struct activator * activator = malloc(sizeof(*activator)); + activator->context=context; + activator->customizer = NULL; + activator->tracker= NULL; + activator->benchmarks = NULL; + activator->freqService = NULL; + + LIST_INIT(&activator->benchmarkEntries); + + *userData = activator; + + return CELIX_SUCCESS; +} + +celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = userData; + + pthread_mutex_init(&activator->mutex, NULL); + + arrayList_create(&activator->benchmarks); + + serviceTrackerCustomizer_create(activator, benchmarkRunner_addingService, benchmarkRunner_addedService, benchmarkRunner_modifiedService, benchmarkRunner_removedService, &activator->customizer); + + char filter[128]; + sprintf(filter, "(|(%s=%s)(%s=%s))", "objectClass", BENCHMARK_SERVICE_NAME, "objectClass", FREQUENCY_SERVICE_NAME); + serviceTracker_createWithFilter(context, filter, activator->customizer, &activator->tracker); + serviceTracker_open(activator->tracker); + + pthread_create(&activator->thread, NULL, (void *)benchmarkRunner_runBenchmark, activator); + + return status; +} + + +celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) { + struct activator * activator = userData; + + pthread_join(activator->thread, NULL); + + serviceTracker_close(activator->tracker); + + return CELIX_SUCCESS; +} + +celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) { + struct activator * activator = userData; + + return CELIX_SUCCESS; +} + +static celix_status_t benchmarkRunner_addingService(void * handle, service_reference_pt reference, void **service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + status = bundleContext_getService(activator->context, reference, service); + return status; + +} +static celix_status_t benchmarkRunner_addedService(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + + service_registration_pt registration = NULL; + properties_pt properties = NULL; + char *serviceName = NULL; + serviceReference_getServiceRegistration(reference, ®istration); + serviceRegistration_getProperties(registration, &properties); + serviceName = properties_get(properties, "objectClass"); + if (strcmp(serviceName, BENCHMARK_SERVICE_NAME) == 0) { + pthread_mutex_lock(&activator->mutex); + arrayList_add(activator->benchmarks, service); + pthread_mutex_unlock(&activator->mutex); + } else if (strcmp(serviceName, FREQUENCY_SERVICE_NAME) == 0 ) { + pthread_mutex_lock(&activator->mutex); + activator->freqService = service; + pthread_mutex_unlock(&activator->mutex); + } + + return status; +} +static celix_status_t benchmarkRunner_modifiedService(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + return status; +} + +static celix_status_t benchmarkRunner_removedService(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + + service_registration_pt registration = NULL; + properties_pt properties = NULL; + char *serviceName = NULL; + serviceReference_getServiceRegistration(reference, ®istration); + serviceRegistration_getProperties(registration, &properties); + serviceName = properties_get(properties, "objectClass"); + if (strcmp(serviceName, BENCHMARK_SERVICE_NAME) == 0) { + pthread_mutex_lock(&activator->mutex); + arrayList_removeElement(activator->benchmarks, service); + pthread_mutex_unlock(&activator->mutex); + } else if (strcmp(serviceName, FREQUENCY_SERVICE_NAME) == 0 ) { + pthread_mutex_lock(&activator->mutex); + if (activator->freqService == service) { + activator->freqService = NULL; + } + pthread_mutex_unlock(&activator->mutex); + } + + return status; +} + +static void benchmarkRunner_runBenchmark(struct activator *activator) { + int i, k; + int nrOfBenchmarks; + double updateFrequency, measuredFrequency; + unsigned int measuredUpdateCounter, nrOfUpdateThreads; + int nrOfSamples; + benchmark_service_pt benchmarkServ; + char *name; + benchmark_result_t result; + struct timeval begin,end; + unsigned long elapsedTime; + double sampleFactor; + + int nrOfThreadRuns = 12; + int threads[] = {1,2,3,4,5,6,7,8,16,32,64,128}; + + nrOfSamples = 100 * 1000; + updateFrequency = 1000; + nrOfUpdateThreads = 100; + + usleep(2000 * 1000); //wait 2 seconds to get needed services + + pthread_mutex_lock(&activator->mutex); + if (activator->freqService != NULL) { + activator->freqService->setFrequency(activator->freqService->handle, updateFrequency); + activator->freqService->setNrOfThreads(activator->freqService->handle, nrOfUpdateThreads); + } + nrOfBenchmarks = arrayList_size(activator->benchmarks); + for (i = 0 ; i < nrOfBenchmarks ; i += 1) { + benchmarkServ = arrayList_get(activator->benchmarks, i); + name = benchmarkServ->name(benchmarkServ->handler); + sampleFactor = benchmarkServ->getSampleFactor(benchmarkServ->handler); + activator->freqService->setBenchmarkName(activator->freqService->handle, name); + usleep(1000); + benchmarkRunner_printHeader(name, nrOfSamples * sampleFactor); + for (k = 0 ; k < nrOfThreadRuns ; k +=1) { + if (activator->freqService != NULL) { + activator->freqService->resetCounter(activator->freqService->handle); + + } + gettimeofday(&begin, NULL); + result = benchmarkServ->run(benchmarkServ->handler, threads[k], nrOfSamples * sampleFactor); + gettimeofday(&end, NULL); + elapsedTime = ((end.tv_sec - begin.tv_sec) * 1000000) + (end.tv_usec - begin.tv_usec); + if (activator->freqService != NULL) { + measuredUpdateCounter = activator->freqService->getCounter(activator->freqService->handle); + measuredFrequency = ((double)(measuredUpdateCounter) / elapsedTime * 1000000); + } + benchmarkRunner_printResult(result, measuredFrequency, elapsedTime); + } + benchmarkRunner_printFooter(name); + } + pthread_mutex_unlock(&activator->mutex); +} + +static void benchmarkRunner_printHeader(char *name, unsigned int nrOfSamples) { + int i; + printf("---% 35s---------------------------------------------------------------------------------------\n", name); + printf("-------samples: %10i---------------------------------------------------------------------------------------------------\n", nrOfSamples); +} + +static void benchmarkRunner_printResult(benchmark_result_t result, double updateFreq, unsigned long elapsedTime) { + printf("| threads %5i | ", result.nrOfThreads); + printf("average call time: % 10.2f nanoseconds | ", result.averageCallTimeInNanoseconds); + printf("frequency calls is % 10.5f MHz | ", result.callFrequencyInMhz); + printf("update freq ~ % 8.2f Hz | ", updateFreq); + printf("elapsed time is % 8.5f seconds | ", ((double)elapsedTime) / 1000000); + printf("\n"); +} + +static void benchmarkRunner_printFooter(char *name) { + printf("-----------------------------------------------------------------------------------------------------------------------------\n\n\n"); +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/benchmark.h ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/public/include/benchmark.h b/examples/locking/benchmark/public/include/benchmark.h new file mode 100644 index 0000000..971f111 --- /dev/null +++ b/examples/locking/benchmark/public/include/benchmark.h @@ -0,0 +1,29 @@ +/* + * consumer.h + * + * Created on: Feb 13, 2014 + * Author: dl436 + */ + +#ifndef CONSUMER_H_ +#define CONSUMER_H_ + +#include "celix_errno.h" + +#include "benchmark_result.h" +#include "math_service.h" + +typedef struct benchmark *benchmark_pt; //ADT + +celix_status_t benchmark_create(benchmark_pt *benchmark); +celix_status_t benchmark_destroy(benchmark_pt benchmark); + +benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples); +char * benchmark_getName(benchmark_pt benchmark); +double benchmark_getSampleFactor(benchmark_pt benchmark); + +celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService); +celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService); + + +#endif /* CONSUMER_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/benchmark_result.h ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/public/include/benchmark_result.h b/examples/locking/benchmark/public/include/benchmark_result.h new file mode 100644 index 0000000..e0750a8 --- /dev/null +++ b/examples/locking/benchmark/public/include/benchmark_result.h @@ -0,0 +1,20 @@ +/* + * benchmark_result.h + * + * Created on: Feb 13, 2014 + * Author: dl436 + */ + +#ifndef BENCHMARK_RESULT_H_ +#define BENCHMARK_RESULT_H_ + +typedef struct benchmark_result { + unsigned int nrOfThreads; + unsigned int nrOfsamples; + unsigned int result; + unsigned int skips; + double averageCallTimeInNanoseconds; + double callFrequencyInMhz; +} benchmark_result_t; + +#endif /* BENCHMARK_RESULT_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/benchmark_service.h ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/public/include/benchmark_service.h b/examples/locking/benchmark/public/include/benchmark_service.h new file mode 100644 index 0000000..63ada04 --- /dev/null +++ b/examples/locking/benchmark/public/include/benchmark_service.h @@ -0,0 +1,27 @@ +/* + * benchmark_service.h + * + * Created on: Feb 13, 2014 + * Author: dl436 + */ + +#ifndef BENCHMARK_SERVICE_H_ +#define BENCHMARK_SERVICE_H_ + +#include "benchmark_result.h" + +typedef struct benchmark_service *benchmark_service_pt; + +typedef struct benchmark_handler *benchmark_handler_pt; //ADT + +#define BENCHMARK_SERVICE_NAME "benchmark_service" + +struct benchmark_service { + benchmark_handler_pt handler; + + benchmark_result_t (*run)(benchmark_handler_pt handler, int nrOfThreads, int nrOfSamples); + char * (*name)(benchmark_handler_pt handler); + double (*getSampleFactor)(benchmark_handler_pt benchmark); +}; + +#endif /* BENCHMARK_SERVICE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/frequency_service.h ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/public/include/frequency_service.h b/examples/locking/benchmark/public/include/frequency_service.h new file mode 100644 index 0000000..5c022ce --- /dev/null +++ b/examples/locking/benchmark/public/include/frequency_service.h @@ -0,0 +1,47 @@ +/** + *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. + */ +/* + * frequence_service.h + * + * \date Feb 4, 2014 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +//TODO change to math provider service ??? + +#ifndef FREQUENCY_SERVICE_H +#define FREQUENCY_SERVICE_H + +#define FREQUENCY_SERVICE_NAME "frequency_service" + +typedef struct frequency_hander frequence_handler_t; + +struct frequency_service { + frequence_handler_t *handle; + void (*setFrequency)(frequence_handler_t *handle, int freq); + void (*resetCounter)(frequence_handler_t *handle); + uint (*getCounter)(frequence_handler_t *handle); + void (*setBenchmarkName)(frequence_handler_t *handle, char *name); + void (*setNrOfThreads)(frequence_handler_t *handle, uint nrOfThreads); +}; + +typedef struct frequency_service * frequency_service_pt; + +#endif /* FREQUENCY_SERVICE_H */ http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/math_service.h ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/public/include/math_service.h b/examples/locking/benchmark/public/include/math_service.h new file mode 100644 index 0000000..154cc9c --- /dev/null +++ b/examples/locking/benchmark/public/include/math_service.h @@ -0,0 +1,40 @@ +/** + *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. + */ +/* + * echo_server.h + * + * \date Sep 21, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef MATH_SERVICE_H +#define MATH_SERVICE_H + +#define MATH_SERVICE_NAME "math_service" + + +struct math_service { + void *handle; + int (*calc)(void *handle, int arg1, int arg2); +}; + +typedef struct math_service * math_service_pt; + +#endif /* MATH_SERVICE_H */ http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/src/benchmark_activator.c ---------------------------------------------------------------------- diff --git a/examples/locking/benchmark/public/src/benchmark_activator.c b/examples/locking/benchmark/public/src/benchmark_activator.c new file mode 100644 index 0000000..a161f11 --- /dev/null +++ b/examples/locking/benchmark/public/src/benchmark_activator.c @@ -0,0 +1,133 @@ +/** + *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. + */ +/* + * echo_server_activator.c + * + * \date Sep 21, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdlib.h> +#include <unistd.h> + +#include "bundle_activator.h" +#include "bundle_context.h" +#include "service_registration.h" +#include "service_tracker.h" + +#include "math_service.h" +#include "benchmark.h" +#include "benchmark_service.h" +#include "frequency_service.h" + +static celix_status_t addingService(void * handle, service_reference_pt reference, void **service); +static celix_status_t addedService(void * handle, service_reference_pt reference, void * service); +static celix_status_t modifiedService(void * handle, service_reference_pt reference, void * service); +static celix_status_t removedService(void * handle, service_reference_pt reference, void * service); + +struct activator { + bundle_context_pt context; + benchmark_pt benchmark; + benchmark_service_pt mathService; + service_tracker_customizer_pt customizer; + service_tracker_pt tracker; + service_registration_pt registration; +}; + +celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { + struct activator * activator = malloc(sizeof(*activator)); + activator->context=context; + activator->benchmark=NULL; + activator->mathService = NULL; + activator->customizer = NULL; + activator->tracker=NULL; + activator->registration = NULL; + + *userData = activator; + + return CELIX_SUCCESS; +} + +celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = userData; + + status = benchmark_create(&activator->benchmark); + serviceTrackerCustomizer_create(activator, addingService, addedService, modifiedService, removedService, &activator->customizer); + + char filter[128]; + sprintf(filter, "(&(objectClass=%s)(benchmark=%s))", MATH_SERVICE_NAME, benchmark_getName(activator->benchmark)); + + serviceTracker_createWithFilter(context, filter, activator->customizer, &activator->tracker); + serviceTracker_open(activator->tracker); + + activator->mathService = malloc(sizeof(*activator->mathService)); + activator->mathService->handler = (void *)activator->benchmark; + activator->mathService->name=(void *)benchmark_getName; + activator->mathService->getSampleFactor=(void *)benchmark_getSampleFactor; + activator->mathService->run=(void *)benchmark_run; + + status = bundleContext_registerService(activator->context, BENCHMARK_SERVICE_NAME, activator->mathService, NULL, &activator->registration); + + return status; +} + + +celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) { + struct activator * activator = userData; + + serviceTracker_close(activator->tracker); + + return CELIX_SUCCESS; +} + +celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) { + struct activator * activator = userData; + + benchmark_destroy(activator->benchmark); + activator->benchmark=NULL; + + return CELIX_SUCCESS; +} + +static celix_status_t addingService(void * handle, service_reference_pt reference, void **service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + status = bundleContext_getService(activator->context, reference, service); + return status; + +} +static celix_status_t addedService(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + benchmark_addMathService(activator->benchmark, service); + return status; +} +static celix_status_t modifiedService(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + return status; +} + +static celix_status_t removedService(void * handle, service_reference_pt reference, void * service) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = handle; + benchmark_removeMathService(activator->benchmark, service); + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/consumer.c ---------------------------------------------------------------------- diff --git a/examples/locking/consumer.c b/examples/locking/consumer.c new file mode 100644 index 0000000..b73549e --- /dev/null +++ b/examples/locking/consumer.c @@ -0,0 +1,372 @@ +/** + *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. + */ +/* + * consumer.c + * + * \date Feb 3, 2014 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#include "consumer.h" + +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <sys/time.h> +#include <unistd.h> +#include <pthread.h> + +#include <urcu.h> + +#include "math_service.h" +#include "frequency_service.h" + +#define FREELIST_LENGTH 16 + +typedef union service_counter service_counter_t; + +union service_counter { + volatile struct { + volatile u_int32_t counter; //TODO FIXME assuming little endian!! + volatile u_int32_t position; + math_service_pt math; // not accesible by raw + } info; //TODO rename data + volatile u_int64_t data; //TODO rename raw +}; + +struct consumer { + math_service_pt math; + frequency_service_pt frequencyService; + locking_type_t currentLockingType; + pthread_mutex_t mutex; + pthread_rwlock_t rw_lock; + service_counter_t *counters[FREELIST_LENGTH]; + service_counter_t *current; +}; + +typedef struct run_info { + consumer_pt consumer; + volatile locking_type_t type; + int nrOfsamples; + int result; + uint skips; + uint updateCounter; + struct timeval begin; + struct timeval end; +} run_info_t; + +static void * consumer_reference_run(run_info_t *info); +static void * consumer_no_locking_run(run_info_t *info); +static void * consumer_mutex_run(run_info_t *info); +static void * consumer_rcu_run(run_info_t *info); +static void * consumer_reference_counting_run(run_info_t *info); +static void * consumer_rw_lock_run(run_info_t *info); + +static int consumer_reference_calc(int arg1, int arg2); + +celix_status_t consumer_create(consumer_pt *result) { + consumer_pt consumer = malloc(sizeof(*consumer)); + consumer->math = NULL; + consumer->frequencyService = NULL; + consumer->currentLockingType=LOCKING_TYPE_NO_LOCKING; + + + service_counter_t *new = malloc(sizeof(service_counter_t)); + new->info.position = 0; + new->info.counter = 0; + new->info.math = NULL; + + int i; + for (i = 0; i < FREELIST_LENGTH; i+=1) { + consumer->counters[i] = NULL; + } + consumer->current = new; + consumer->counters[0] = new; + + pthread_mutex_init(&consumer->mutex, NULL); + pthread_rwlock_init(&consumer->rw_lock, NULL); + + rcu_init(); + + (*result) = consumer; + return CELIX_SUCCESS; +} + +celix_status_t consumer_destroy(consumer_pt consumer) { + pthread_mutex_destroy(&consumer->mutex); + pthread_rwlock_destroy(&consumer->rw_lock); + free(consumer); + return CELIX_SUCCESS; +} + +void consumer_setFrequencyService(consumer_pt consumer, frequency_service_pt freqServ) { + consumer->frequencyService=freqServ; +} + +void consumer_runBenchmark(consumer_pt consumer, locking_type_t type, int nrOfThreads, int nrOfSamples) { + pthread_t threads[nrOfThreads]; + run_info_t info[nrOfThreads]; + int elapsedTime, skips, counter; + double callTime, callFreq, updateFreq; + int i; + + consumer->currentLockingType=type; + usleep(1000); + + //init + for (i = 0; i< nrOfThreads; i += 1) { + info[i].consumer = consumer; + info[i].nrOfsamples=nrOfSamples; + info[i].result = rand(); + info[i].skips = 0; + info[i].updateCounter = 0; + } + elapsedTime = 0; + skips = 0; + + //start threads + info->consumer->frequencyService->resetCounter(info->consumer->frequencyService->handler); + for (i = 0; i < nrOfThreads; i += 1) { + if (type == LOCKING_TYPE_NO_LOCKING) { + pthread_create(&threads[i], NULL, (void *)consumer_no_locking_run, &info[i]); + } else if (type == LOCKING_TYPE_MUTEX) { + pthread_create(&threads[i], NULL, (void *)consumer_mutex_run, &info[i]); + } else if (type == LOCKING_TYPE_REFERENCE) { + pthread_create(&threads[i], NULL, (void *)consumer_reference_run, &info[i]); + } else if (type == LOCKING_TYPE_RCU) { + pthread_create(&threads[i], NULL, (void *)consumer_rcu_run, &info[i]); + } else if (type == LOCKING_TYPE_REFERENCE_COUNTER) { + pthread_create(&threads[i], NULL, (void *)consumer_reference_counting_run, &info[i]); + } else if (type == LOCKING_TYPE_RW_LOCK) { + pthread_create(&threads[i], NULL, (void *)consumer_rw_lock_run, &info[i]); + } else { + printf ("unknown type\n"); + return; + } + } + + //join and print result + + for (i = 0; i < nrOfThreads; i +=1 ) { + pthread_join(threads[i], NULL); + elapsedTime += ((info[i].end.tv_sec - info[i].begin.tv_sec) * 1000000) + (info[i].end.tv_usec - info[i].begin.tv_usec); + skips += info[i].skips; + counter += info[i].updateCounter; + } + counter = info->consumer->frequencyService->getCounter(info->consumer->frequencyService->handler); + callTime = ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads); + callFreq = ((double)(nrOfSamples * nrOfThreads) / elapsedTime); + updateFreq = ((double)counter * 1000000) / elapsedTime; + printf("| threads %5i | ", nrOfThreads); + printf("average call time: % 10.2f nanoseconds | ", callTime); + printf("frequency calls is % 10.5f MHz | ", callFreq); + printf("update freq ~ % 8.2f Hz | ", updateFreq); + printf("\n"); + + if (skips > 0) { + printf("WARNING skips is %i\n", skips); + } +} + +celix_status_t consumer_addMathService(consumer_pt consumer, math_service_pt mathService) { + if (consumer->currentLockingType == LOCKING_TYPE_MUTEX) { + pthread_mutex_lock(&consumer->mutex); + consumer->math = mathService; + pthread_mutex_unlock(&consumer->mutex); + } else if (consumer->currentLockingType == LOCKING_TYPE_RCU) { + consumer->math = mathService; + synchronize_rcu(); + } else if (consumer->currentLockingType == LOCKING_TYPE_RW_LOCK) { + pthread_rwlock_wrlock(&consumer->rw_lock); + consumer->math = mathService; + pthread_rwlock_unlock(&consumer->rw_lock); + } else { //no locking + consumer->math = mathService; + } + + //always update for reference counter +// service_counter_t *new = malloc(sizeof(service_counter_t)); +// new->info.position = 0; +// new->info.counter = 0; +// new->info.math = mathService; +// int found = false; +// int pos; +// for (pos = 0; !found && pos < FREELIST_LENGTH; pos += 1) { +// found = __sync_bool_compare_and_swap(&(consumer->counters[pos]), NULL, new); +// if (found) { +// new->info.position = pos; +// break; +// } +// } +// +// if (!found) { +// printf("Cannot find free spot!!!!, will use 0\n"); +// consumer->counters[0] = new; +// } +// +// int changed = false; +// service_counter_t *old; +// while (!changed) { +// old = consumer->current; +// changed = __sync_bool_compare_and_swap(&consumer->current, old, new); +// } +// +// while (old->info.counter != 0) {usleep(10);} +// consumer->counters[old->info.position] = NULL; +// free(old); + + return CELIX_SUCCESS; +} + +celix_status_t consumer_removeMathService(consumer_pt consumer, math_service_pt mathService) { + if (consumer->currentLockingType == LOCKING_TYPE_NO_LOCKING) { + __sync_val_compare_and_swap(&consumer->math, mathService, NULL); + } else if (consumer->currentLockingType == LOCKING_TYPE_MUTEX) { + pthread_mutex_lock(&consumer->mutex); + if (consumer->math == mathService) { + consumer->math = NULL; + } + pthread_mutex_unlock(&consumer->mutex); + } else if (consumer->currentLockingType == LOCKING_TYPE_RCU) { + uatomic_cmpxchg(&consumer->math, mathService, NULL); + } else if (consumer->currentLockingType == LOCKING_TYPE_REFERENCE_COUNTER) { + //TODO DONT KNOWN IGNORE FOR NOW + } + return CELIX_SUCCESS; +} + +static void * consumer_reference_run(run_info_t *info) { + int i; + + gettimeofday(&info->begin, NULL); + for (i = 0; i < info->nrOfsamples; i += 1) { + info->result = consumer_reference_calc(info->result, i); + } + gettimeofday(&info->end, NULL); + return NULL; +} + +static void * consumer_no_locking_run(run_info_t *info) { + int i; + + gettimeofday(&info->begin, NULL); + for (i = 0; i < info->nrOfsamples; i += 1) { + if (info->consumer->math != NULL) { + info->result = info->consumer->math->calc(info->result, i); + } else { + info->skips +=1; //should not happen + } + } + gettimeofday(&info->end, NULL); + return NULL; +} + +static void * consumer_mutex_run(run_info_t *info) { + int i; + + gettimeofday(&info->begin, NULL); + for (i = 0; i < info->nrOfsamples; i += 1) { + pthread_mutex_lock(&info->consumer->mutex); + if (info->consumer->math != NULL) { + info->result = info->consumer->math->calc(info->result, i); + } else { + info->skips += 1; //should not happen + } + pthread_mutex_unlock(&info->consumer->mutex); + } + gettimeofday(&info->end, NULL); + return NULL; +} + +static void * consumer_rw_lock_run(run_info_t *info) { + int i; + consumer_pt cons = info->consumer; + int result = info->result; + pthread_rwlock_t *lock = &cons->rw_lock; + int nrOfsamples = info->nrOfsamples; + + gettimeofday(&info->begin, NULL); + for (i = 0; i < nrOfsamples; i += 1) { + pthread_rwlock_rdlock(lock); + if (cons->math != NULL) { + result = cons->math->calc(result, i); + } else { + info->skips += 1; //should not happen + } + pthread_rwlock_unlock(lock); + } + gettimeofday(&info->end, NULL); + info->result = result; + return NULL; +} + +static void * consumer_rcu_run(run_info_t *info) { + rcu_register_thread(); + int i; + math_service_pt service; + + gettimeofday(&info->begin, NULL); + for (i = 0; i < info->nrOfsamples; i += 1) { + rcu_read_lock(); + if (info->consumer->math != NULL) { + info->result = info->consumer->math->calc(info->result, i); + } else { + info->skips +=1; //should not happen + } + rcu_read_unlock(); + } + gettimeofday(&info->end, NULL); + rcu_unregister_thread(); + return NULL; +} + +static void * consumer_reference_counting_run(run_info_t *info) { + int i; + service_counter_t posAndCount; + + gettimeofday(&info->begin, NULL); + for (i = 0; i < info->nrOfsamples; i += 1) { + posAndCount.data = __sync_add_and_fetch((u_int64_t *)&info->consumer->current->data, 1); + volatile service_counter_t *serv = (volatile void *)info->consumer->counters[posAndCount.info.position]; + if (serv->info.math != NULL) { + info->result = serv->info.math->calc(info->result, i); + } else { + info->skips += 1; + } + __sync_sub_and_fetch((u_int64_t *)&serv->data, -1); + + //not service_counter will not be deleted...but can we still find it??? is info->consumer->serviceCounter still te same? + //change write to swap compare and then only changing the pointer is the counter is null?? not possible.. can compare counter , but not change pointer + + //IDEA create a list with service_counter based on a id (number) this number is 32bit long and put a counter + id in a 64bit value. + //use this value to atomic increment and return value and use the id to retrieve the actual pointer. the value can be stored in the heap. + //A list with id is used to retrieve a pointer to the service. If the value is null the slot is available this can be check with + //compare_and_swap while looping through the list. The list can be extended when the end is reached and then a next list pointer can + //be used. This can also be a linked list and the limitation is the max 32bit uint value (of 16bits for 32bit platforms). + } + + gettimeofday(&info->end, NULL); + return NULL; +} + +//NOTE: copy implementation of the math_service->calc function, for reference. +static int consumer_reference_calc(int arg1, int arg2) { + return arg1 * arg2 + arg2; +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/locking/math_provider/CMakeLists.txt b/examples/locking/math_provider/CMakeLists.txt new file mode 100644 index 0000000..288d6ba --- /dev/null +++ b/examples/locking/math_provider/CMakeLists.txt @@ -0,0 +1,32 @@ +# 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. + +SET(BUNDLE_SYMBOLICNAME math_provider) +SET(BUNDLE_VERSION 0.0.0) + +bundle(math_provider SOURCES + private/src/provider_activator + private/src/math_component +) + +include_directories(public/include) +include_directories(../benchmark/public/include) +include_directories("${PROJECT_SOURCE_DIR}/framework/public/include") +include_directories("${PROJECT_SOURCE_DIR}/utils/public/include") +include_directories("${PROJECT_SOURCE_DIR}/shell/public/include") +include_directories(private/include) +target_link_libraries(math_provider celix_framework) http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/private/include/math_component.h ---------------------------------------------------------------------- diff --git a/examples/locking/math_provider/private/include/math_component.h b/examples/locking/math_provider/private/include/math_component.h new file mode 100644 index 0000000..0b55d10 --- /dev/null +++ b/examples/locking/math_provider/private/include/math_component.h @@ -0,0 +1,14 @@ +#ifndef MATH_COMPONENT_H_ +#define MATH_COMPONENT_H_ + +#include "celix_errno.h" + +typedef struct math_component *math_component_pt; + +celix_status_t mathComponent_create(math_component_pt *math); +celix_status_t mathComponent_destroy(math_component_pt math); + +int mathComponent_calc(math_component_pt math, int arg1, int arg2); + + +#endif /* MATH_COMPONENT_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/private/src/math_component.c ---------------------------------------------------------------------- diff --git a/examples/locking/math_provider/private/src/math_component.c b/examples/locking/math_provider/private/src/math_component.c new file mode 100644 index 0000000..2937fee --- /dev/null +++ b/examples/locking/math_provider/private/src/math_component.c @@ -0,0 +1,28 @@ +/* + * math.c + * + * Created on: Oct 8, 2014 + * Author: dl436 + */ + +#include "math_component.h" + +struct math_component { + //emtpy +}; + +celix_status_t mathComponent_create(math_component_pt *math) { + (*math) = malloc(sizeof(struct math_component)); + return CELIX_SUCCESS; +} + +celix_status_t mathComponent_destroy(math_component_pt math) { + free(math); + return CELIX_SUCCESS; +} + +int mathComponent_calc(math_component_pt math, int arg1, int arg2) { + return arg1 * arg2 + arg2; +} + + http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/private/src/provider_activator.c ---------------------------------------------------------------------- diff --git a/examples/locking/math_provider/private/src/provider_activator.c b/examples/locking/math_provider/private/src/provider_activator.c new file mode 100644 index 0000000..319980f --- /dev/null +++ b/examples/locking/math_provider/private/src/provider_activator.c @@ -0,0 +1,219 @@ +/** + *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. + */ +/* + * echo_server_activator.c + * + * \date Sep 21, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdlib.h> +#include <unistd.h> +#include <stdbool.h> +#include <sys/time.h> + +#include "bundle_activator.h" +#include "bundle_context.h" +#include "service_registration.h" + +#include "math_service.h" +#include "frequency_service.h" +#include "math_component.h" + +typedef struct activator { + bundle_context_pt context; + + frequency_service_pt freqService; + service_registration_pt freqRegistration; + + math_component_pt math; + math_service_pt mathService; + char *benchmarkName; + service_registration_pt registration; + + uint updateFrequency; + uint nrOfThreads; + pthread_t *threads; + + + volatile uint counter; + struct timeval beginMeasurement; + struct timeval endMeasurement; +} activator_t; + +static int calc(int arg1, int arg2); +static void run(activator_t *activator); +static void setFrequency(activator_t *activator, uint freq); +static void setNrOfThreads(activator_t *activator, uint nrOfThreads); +static void resetCounter(activator_t *activator); +static void stopThreads(activator_t *activator); +static void startThreads(activator_t *activator, uint nrOfThreads); +static uint getCounter(activator_t *activator); +static void setBenchmarkName(activator_t *activator, char *benchmark); +static math_service_pt registerMath(activator_t *activator, service_registration_pt *reg); + +celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { + activator_t * activator = malloc(sizeof(*activator)); + activator->context = context; + activator->benchmarkName = NULL; + activator->freqService = NULL; + activator->freqRegistration = NULL; + activator->updateFrequency = 0; + activator->nrOfThreads = 0; + activator->math = NULL; + + mathComponent_create(&activator->math); + + *userData = activator; + + return CELIX_SUCCESS; +} + +celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + struct activator * activator = userData; + + activator->mathService = malloc(sizeof(*activator->mathService)); + activator->mathService->handle = activator->math; + activator->mathService->calc = (void *)mathComponent_calc; + bundleContext_registerService(activator->context, MATH_SERVICE_NAME, activator->mathService, NULL, &activator->registration); + + activator->freqService = malloc(sizeof(*activator->freqService)); + activator->freqService->handle = (void *)activator; + activator->freqService->setFrequency = (void *)setFrequency; + activator->freqService->resetCounter = (void *)resetCounter; + activator->freqService->getCounter = (void *)getCounter; + activator->freqService->setBenchmarkName = (void *)setBenchmarkName; + activator->freqService->setNrOfThreads = (void *)setNrOfThreads; + bundleContext_registerService(activator->context, FREQUENCY_SERVICE_NAME, activator->freqService, NULL, &activator->freqRegistration); + + startThreads(activator, activator->nrOfThreads); + + return status; +} + +celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) { + struct activator * activator = userData; + + printf("Stopping service registration thread\n"); + stopThreads(activator); + + //TODO deregister service & freqService + + return CELIX_SUCCESS; +} + +celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) { + struct echoActivator * activator = userData; + + //TODO free service & freqService struct + + free(activator); + + return CELIX_SUCCESS; +} + +static int calc(int arg1, int arg2) { + return arg1 * arg2 + arg2; +} + +static void stopThreads(activator_t *activator) { + //cancel and join threads + if (activator->threads != NULL) { + for (int i = 0 ; i < activator->nrOfThreads ; i += 1) { + pthread_cancel(activator->threads[i]); + pthread_join(activator->threads[i], NULL); + } + } +} + +static void startThreads(activator_t *activator, uint nrOfThreads) { + activator->threads = malloc(sizeof(pthread_t) * nrOfThreads); + for (int i = 0 ; i < nrOfThreads ; i += 1) { + pthread_create(&activator->threads[i], NULL, (void *)run, activator); + } + activator->nrOfThreads = nrOfThreads; +} + +static void run(activator_t *activator) { + service_registration_pt currentReg = NULL; + service_registration_pt prevReg = NULL; + math_service_pt current = NULL; + math_service_pt prev = NULL; + while (1) { + pthread_testcancel(); //NOTE no clean exit still need to clear a register service + uint delayInMicroseconds = activator->updateFrequency == 0 ? 0 : (1000 * 1000) / activator->updateFrequency; + if (delayInMicroseconds > 0) { + prevReg = currentReg; + prev = current; + + currentReg = NULL; + current = registerMath(activator, ¤tReg); + + if (prevReg != NULL) { + serviceRegistration_unregister(prevReg); + free(prev); + } + } + usleep(delayInMicroseconds > 0 ? delayInMicroseconds : 1000000); + } +} + +static math_service_pt registerMath(activator_t *activator, service_registration_pt *reg) { + math_service_pt serv = NULL; + serv = malloc(sizeof(*activator->mathService)); + serv->handle = activator->math; + serv->calc = (void *)mathComponent_calc; + properties_pt props = properties_create(); + if (activator->benchmarkName != NULL) { //TODO FIXME race condition + properties_set(props, "benchmark", activator->benchmarkName); + } + bundleContext_registerService(activator->context, MATH_SERVICE_NAME, + serv, props, reg); + activator->counter += 1; + return serv; +} + +static void setBenchmarkName(activator_t *activator, char *benchmark) { + char *old = activator->benchmarkName; + activator->benchmarkName = strdup(benchmark); + free(old); + if (activator->updateFrequency == 0) { + service_registration_pt reg = NULL; + registerMath(activator, ®); //TODO service will not be cleaned up ! + } +} + +static void setFrequency(activator_t *activator, uint freq) { + printf("Setting frequency to %i\n", freq); + activator->updateFrequency = freq; +} + +static void setNrOfThreads(activator_t *activator, uint nrOfThreads) { + stopThreads(activator); + startThreads(activator, nrOfThreads); +} + +static void resetCounter(activator_t *activator) { + activator->counter = 0; +} + +static uint getCounter(activator_t *activator) { + return activator->counter; +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/modified_bool_benchmark/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/locking/modified_bool_benchmark/CMakeLists.txt b/examples/locking/modified_bool_benchmark/CMakeLists.txt new file mode 100644 index 0000000..46ceb7a --- /dev/null +++ b/examples/locking/modified_bool_benchmark/CMakeLists.txt @@ -0,0 +1,32 @@ +# 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. + +SET(BUNDLE_SYMBOLICNAME bool_benchmark) +SET(BUNDLE_VERSION 0.0.0) + +bundle(modified_bool_benchmark SOURCES + ../benchmark/public/src/benchmark_activator + private/src/modified_bool_benchmark +) + +include_directories(public/include) +include_directories(../benchmark/public/include) +include_directories("${PROJECT_SOURCE_DIR}/framework/public/include") +include_directories("${PROJECT_SOURCE_DIR}/utils/public/include") +include_directories("${PROJECT_SOURCE_DIR}/shell/public/include") +target_link_libraries(modified_bool_benchmark celix_framework) + http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c ---------------------------------------------------------------------- diff --git a/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c b/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c new file mode 100644 index 0000000..b482b2c --- /dev/null +++ b/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c @@ -0,0 +1,162 @@ +#include <stdlib.h> +#include <pthread.h> +#include <unistd.h> +#include <sys/time.h> +#include <pthread.h> + +#include "array_list.h" + +#include "benchmark.h" +#include "math_service.h" + +static const char * const BENCHMARK_NAME = "MODIFIED_BIT"; +static const double SAMPLE_FACTOR = 1; +static const useconds_t SLEEP_TIME = 10; + +typedef struct thread_info { + benchmark_pt benchmark; + unsigned int result; + struct timeval begin; + struct timeval end; + int skips; + bool isModified; + bool isUpdated; +} thread_info_t; + +struct benchmark { + pthread_mutex_t mutex; + math_service_pt math; + int nrOfSamples; + int nrOfThreads; + thread_info_t *threads; +}; + +static void benchmark_thread(thread_info_t *info); + +celix_status_t benchmark_create(benchmark_pt *benchmark) { + (*benchmark) = malloc(sizeof(struct benchmark)); + (*benchmark)->math = NULL; + pthread_mutex_init(&(*benchmark)->mutex, NULL); + return CELIX_SUCCESS; +} + +celix_status_t benchmark_destroy(benchmark_pt benchmark) { + //free threads array + free(benchmark); + return CELIX_SUCCESS; +} + +benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) { + int i; + pthread_t threads[nrOfThreads]; + thread_info_t infos[nrOfThreads]; + benchmark_result_t result; + unsigned long elapsedTime = 0; + + benchmark->threads = infos; + benchmark->nrOfSamples = nrOfSamples; + benchmark->nrOfThreads = nrOfThreads; + + result.skips =0; + pthread_mutex_lock(&benchmark->mutex); + for (i = 0 ; i < nrOfThreads ; i += 1) { + infos[i].benchmark = benchmark; + infos[i].skips = 0; + infos[i].result = rand(); + infos[i].isUpdated = false; + infos[i].isModified = false; + pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]); + } + pthread_mutex_unlock(&benchmark->mutex); + + for (i = 0; i < nrOfThreads ; i += 1) { + pthread_join(threads[i], NULL); + elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec); + result.skips += infos[i].skips; + } + + result.averageCallTimeInNanoseconds = ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads); + result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime); + result.nrOfThreads = nrOfThreads; + result.nrOfsamples = nrOfSamples; + + return result; +} + +static void benchmark_thread(thread_info_t *info) { + int i = 0; + + math_service_pt local = info->benchmark->math; + int nrOfSamples = info->benchmark->nrOfSamples; + + gettimeofday(&info->begin, NULL); + while (i < nrOfSamples) { + if (!info->isModified) { + if (local != NULL) { + info->result = local->calc(local->handle, info->result, i); + } else { + info->skips += 1; //should not happen + } + i += 1; + } else { + local = info->benchmark->math; + info->isModified = false; + } + } + gettimeofday(&info->end, NULL); + +} + +char * benchmark_getName(benchmark_pt benchmark) { + return (char *)BENCHMARK_NAME; +} + +celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) { + int i; + + pthread_mutex_lock(&benchmark->mutex); + benchmark->math = mathService; + pthread_mutex_unlock(&benchmark->mutex); + + //inform threads to update servicd + for (i = 0 ; i < benchmark->nrOfSamples ; i += 1) { + benchmark->threads[i].isModified = true; + } + + //Wait till al thread are not in a modified state, e.g. update to date mathService and not using the old service + for (i = 0; i < benchmark->nrOfThreads ; i += 1) { + if (benchmark->threads[i].isModified) { + usleep(SLEEP_TIME); + } + } + + return CELIX_SUCCESS; +} + +celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) { + pthread_mutex_lock(&benchmark->mutex); + if (benchmark->math == mathService) { + benchmark->math = NULL; + } + pthread_mutex_unlock(&benchmark->mutex); + + //inform threads to update servicd + int i; + for (i = 0 ; i < benchmark->nrOfThreads ; i += 1) { + benchmark->threads[i].isModified = true; + } + + //Wait till al thread are not in a modified state, e.g. update to date mathService and not using the old service + for (i = 0; i < benchmark->nrOfThreads ; i += 1) { + if (benchmark->threads[i].isModified) { + usleep(SLEEP_TIME); + } + } + + + return CELIX_SUCCESS; +} + +double benchmark_getSampleFactor(benchmark_pt benchmark) { + return SAMPLE_FACTOR; +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/mutex_benchmark/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/locking/mutex_benchmark/CMakeLists.txt b/examples/locking/mutex_benchmark/CMakeLists.txt new file mode 100644 index 0000000..b822ffa --- /dev/null +++ b/examples/locking/mutex_benchmark/CMakeLists.txt @@ -0,0 +1,32 @@ +# 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. + +SET(BUNDLE_SYMBOLICNAME mutex_benchmark) +SET(BUNDLE_VERSION 0.0.0) + +bundle(mutex_benchmark SOURCES + ../benchmark/public/src/benchmark_activator + private/src/mutex_benchmark +) + +include_directories(public/include) +include_directories(../benchmark/public/include) +include_directories("${PROJECT_SOURCE_DIR}/framework/public/include") +include_directories("${PROJECT_SOURCE_DIR}/utils/public/include") +include_directories("${PROJECT_SOURCE_DIR}/shell/public/include") +target_link_libraries(mutex_benchmark celix_framework) + http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c ---------------------------------------------------------------------- diff --git a/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c b/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c new file mode 100644 index 0000000..3cacfb8 --- /dev/null +++ b/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c @@ -0,0 +1,117 @@ +/* + * mutex_benchmark.c + * + * Created on: Feb 13, 2014 + * Author: dl436 + */ + +#include <stdlib.h> +#include <pthread.h> +#include <unistd.h> +#include <sys/time.h> + +#include "benchmark.h" + +static const char * const BENCHMARK_NAME = "MUTEX"; +static const double SAMPLE_FACTOR = 1; + +struct benchmark { + pthread_mutex_t mutex; + math_service_pt math; +}; + +typedef struct thread_info { + benchmark_pt benchmark; + int nrOfSamples; + unsigned int result; + struct timeval begin; + struct timeval end; + int skips; +} thread_info_t; + +static void benchmark_thread(thread_info_t *info); + +celix_status_t benchmark_create(benchmark_pt *benchmark) { + (*benchmark) = malloc(sizeof(struct benchmark)); + (*benchmark)->math = NULL; + pthread_mutex_init(&(*benchmark)->mutex, NULL); + return CELIX_SUCCESS; +} + +celix_status_t benchmark_destroy(benchmark_pt benchmark) { + free(benchmark); + return CELIX_SUCCESS; +} + +benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) { + int i; + pthread_t threads[nrOfThreads]; + thread_info_t infos[nrOfThreads]; + benchmark_result_t result; + unsigned long elapsedTime = 0; + + result.skips =0; + + for (i = 0 ; i < nrOfThreads ; i += 1) { + infos[i].benchmark = benchmark; + infos[i].nrOfSamples = nrOfSamples; + infos[i].skips = 0; + infos[i].result = rand(); + pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]); + } + + for (i = 0; i < nrOfThreads ; i += 1) { + pthread_join(threads[i], NULL); + elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec); + result.skips += infos[i].skips; + } + + result.averageCallTimeInNanoseconds = ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads); + result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime); + result.nrOfThreads = nrOfThreads; + result.nrOfsamples = nrOfSamples; + + return result; +} + +static void benchmark_thread(thread_info_t *info) { + int i; + + gettimeofday(&info->begin, NULL); + for (i = 0; i < info->nrOfSamples; i += 1) { + pthread_mutex_lock(&info->benchmark->mutex); + if (info->benchmark->math != NULL) { + info->result = info->benchmark->math->calc(info->benchmark->math->handle, info->result, i); + } else { + info->skips += 1; //should not happen + } + pthread_mutex_unlock(&info->benchmark->mutex); + } + gettimeofday(&info->end, NULL); + +} + +char * benchmark_getName(benchmark_pt benchmark) { + return (char *)BENCHMARK_NAME; +} + +celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) { + pthread_mutex_lock(&benchmark->mutex); + benchmark->math = mathService; + pthread_mutex_unlock(&benchmark->mutex); + return CELIX_SUCCESS; +} + +celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) { + pthread_mutex_lock(&benchmark->mutex); + if (benchmark->math == mathService) { + benchmark->math = NULL; + } + pthread_mutex_unlock(&benchmark->mutex); + return CELIX_SUCCESS; + +} + +double benchmark_getSampleFactor(benchmark_pt benchmark) { + return SAMPLE_FACTOR; +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/reference_benchmark/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/locking/reference_benchmark/CMakeLists.txt b/examples/locking/reference_benchmark/CMakeLists.txt new file mode 100644 index 0000000..592bb9c --- /dev/null +++ b/examples/locking/reference_benchmark/CMakeLists.txt @@ -0,0 +1,32 @@ +# 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. + +SET(BUNDLE_SYMBOLICNAME reference_benchmark) +SET(BUNDLE_VERSION 0.0.0) + +bundle(reference_benchmark SOURCES + ../benchmark/public/src/benchmark_activator + private/src/reference_benchmark +) + +include_directories(public/include) +include_directories(../benchmark/public/include) +include_directories("${PROJECT_SOURCE_DIR}/framework/public/include") +include_directories("${PROJECT_SOURCE_DIR}/utils/public/include") +include_directories("${PROJECT_SOURCE_DIR}/shell/public/include") +target_link_libraries(reference_benchmark celix_framework) + http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/reference_benchmark/private/src/reference_benchmark.c ---------------------------------------------------------------------- diff --git a/examples/locking/reference_benchmark/private/src/reference_benchmark.c b/examples/locking/reference_benchmark/private/src/reference_benchmark.c new file mode 100644 index 0000000..f4bb93f --- /dev/null +++ b/examples/locking/reference_benchmark/private/src/reference_benchmark.c @@ -0,0 +1,116 @@ +/* + * mutex_benchmark.c + * + * Created on: Feb 13, 2014 + * Author: dl436 + */ + +#include <stdlib.h> +#include <pthread.h> +#include <unistd.h> +#include <sys/time.h> + +#include "benchmark.h" + +static const char * const BENCHMARK_NAME = "REFERENCE"; +static const double SAMPLE_FACTOR = 100; + +typedef struct thread_info { + benchmark_pt benchmark; + int nrOfSamples; + unsigned int result; + struct timeval begin; + struct timeval end; + int skips; +} thread_info_t; + +static void benchmark_thread(thread_info_t *info); +static int benchmark_calc(int arg1, int arg2); + +celix_status_t benchmark_create(benchmark_pt *benchmark) { + //do nothing + return CELIX_SUCCESS; +} + +celix_status_t benchmark_destroy(benchmark_pt benchmark) { + //do nothing + return CELIX_SUCCESS; +} + +benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) { + int i; + pthread_t threads[nrOfThreads]; + thread_info_t infos[nrOfThreads]; + benchmark_result_t result; + unsigned long elapsedTime = 0; + + result.skips =0; + + for (i = 0 ; i < nrOfThreads ; i += 1) { + infos[i].benchmark = benchmark; + infos[i].nrOfSamples = nrOfSamples; + infos[i].skips = 0; + infos[i].result = rand(); + pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]); + } + + for (i = 0; i < nrOfThreads ; i += 1) { + pthread_join(threads[i], NULL); + elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec); + result.skips += infos[i].skips; + } + + result.averageCallTimeInNanoseconds = elapsedTime; + result.averageCallTimeInNanoseconds *= 1000; + result.averageCallTimeInNanoseconds /= nrOfSamples; + result.averageCallTimeInNanoseconds /= nrOfThreads; + result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime); + result.nrOfThreads = nrOfThreads; + result.nrOfsamples = nrOfSamples; + + return result; +} + +static void benchmark_thread(thread_info_t *info) { + int i; + + int result = info->result; + struct timeval *begin = &info->begin; + struct timeval *end = &info->end; + int nrOFSamples = info->nrOfSamples; + + + gettimeofday(begin, NULL); + for (i = 0; i < nrOFSamples; i += 1) { + result = benchmark_calc(result, i); + } + gettimeofday(end, NULL); + + info->result = result; +} + +char * benchmark_getName(benchmark_pt benchmark) { + return (char *)BENCHMARK_NAME; +} + +celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) { + //ignore service is not used + return CELIX_SUCCESS; +} + +celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) { + //ignore service is not used + return CELIX_SUCCESS; + +} + +/* + * Same implementation as the math_service. This function is used a reference. + */ +static int benchmark_calc(int arg1, int arg2) { + return arg1 * arg2 + arg2; +} + +double benchmark_getSampleFactor(benchmark_pt benchmark) { + return SAMPLE_FACTOR; +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/start_stop_benchmark/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/locking/start_stop_benchmark/CMakeLists.txt b/examples/locking/start_stop_benchmark/CMakeLists.txt new file mode 100644 index 0000000..bca651e --- /dev/null +++ b/examples/locking/start_stop_benchmark/CMakeLists.txt @@ -0,0 +1,32 @@ +# 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. + +SET(BUNDLE_SYMBOLICNAME stop_benchmark) +SET(BUNDLE_VERSION 0.0.0) + +bundle(start_stop_benchmark SOURCES + ../benchmark/public/src/benchmark_activator + private/src/start_stop_benchmark +) + +include_directories(public/include) +include_directories(../benchmark/public/include) +include_directories("${PROJECT_SOURCE_DIR}/framework/public/include") +include_directories("${PROJECT_SOURCE_DIR}/utils/public/include") +include_directories("${PROJECT_SOURCE_DIR}/shell/public/include") +target_link_libraries(start_stop_benchmark celix_framework) + http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c ---------------------------------------------------------------------- diff --git a/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c b/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c new file mode 100644 index 0000000..1d445c5 --- /dev/null +++ b/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c @@ -0,0 +1,189 @@ +/* + * mutex_benchmark.c + * + * Created on: Feb 13, 2014 + * Author: dl436 + */ + +#include <stdlib.h> +#include <pthread.h> +#include <unistd.h> +#include <sys/time.h> +#include <stdio.h> + +#include "benchmark.h" + +static const char * const BENCHMARK_NAME = "INTR_CONT"; +static const double SAMPLE_FACTOR = 100; +static const __useconds_t WAIT_TIME = 1; //100 * 1000; + +typedef enum benchmark_state { + BENCHMARK_STATE_INTERRUPTED, + BENCHMARK_STATE_RUNNING +} benchmark_state_t; + +struct benchmark { + int nrOfThreads; + pthread_mutex_t mutex; //write protect for state + math_service_pt math; + benchmark_state_t state; + int threadsRunning; +}; + +typedef struct thread_info { + benchmark_pt benchmark; + int nrOfSamples; + unsigned int result; + struct timeval begin; + struct timeval end; + int skips; +} thread_info_t; + +static void benchmark_thread(thread_info_t *info); +static void benchmark_runSamples(thread_info_t *info, int *i, volatile benchmark_state_t *state); +static void benchmark_interrupt(benchmark_pt benchmark); +static void benchmark_continue(benchmark_pt benchmark); + +celix_status_t benchmark_create(benchmark_pt *benchmark) { + (*benchmark) = malloc(sizeof(struct benchmark)); + (*benchmark)->math = NULL; + (*benchmark)->state = BENCHMARK_STATE_INTERRUPTED; + (*benchmark)->nrOfThreads = 0; + (*benchmark)->threadsRunning = 0; + + pthread_mutex_init(&(*benchmark)->mutex, NULL); + + return CELIX_SUCCESS; +} + +celix_status_t benchmark_destroy(benchmark_pt benchmark) { + free(benchmark); + + return CELIX_SUCCESS; +} + +benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) { + int i; + pthread_t threads[nrOfThreads]; + thread_info_t infos[nrOfThreads]; + int isThreadRunning[nrOfThreads]; + benchmark_result_t result; + unsigned long elapsedTime = 0; + result.skips =0; + + for (i = 0 ; i < nrOfThreads ; i += 1) { + infos[i].benchmark = benchmark; + infos[i].nrOfSamples = nrOfSamples; + infos[i].skips = 0; + infos[i].result = rand(); + pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]); + } + + benchmark->nrOfThreads = nrOfThreads; + + for (i = 0; i < nrOfThreads ; i += 1) { + pthread_join(threads[i], NULL); + elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec); + result.skips += infos[i].skips; + } + + benchmark->nrOfThreads = 0; + + result.averageCallTimeInNanoseconds = elapsedTime; + result.averageCallTimeInNanoseconds *= 1000; + result.averageCallTimeInNanoseconds /= nrOfSamples; + result.averageCallTimeInNanoseconds /= nrOfThreads; + result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime); + result.nrOfThreads = nrOfThreads; + result.nrOfsamples = nrOfSamples; + + return result; +} + +static void benchmark_thread(thread_info_t *info) { + int i = 0; + + gettimeofday(&info->begin, NULL); + while (i < info->nrOfSamples) { + if (info->benchmark->state == BENCHMARK_STATE_RUNNING ) { + //TODO race condition?? or not because of the mutex on changing the state + __sync_add_and_fetch(&info->benchmark->threadsRunning, 1); + benchmark_runSamples(info, &i, &info->benchmark->state); + __sync_sub_and_fetch(&info->benchmark->threadsRunning, 1); + } else { + usleep(WAIT_TIME); + } + } + gettimeofday(&info->end, NULL); + +} + +static void benchmark_runSamples(thread_info_t *info, int *i, volatile benchmark_state_t *state) { + int nrOfSamples = info->nrOfSamples; + unsigned int result = info->result; + math_service_pt math = info->benchmark->math; + + for (; *i < nrOfSamples && *state == BENCHMARK_STATE_RUNNING; *i += 1) { + result = math->calc(math->handle, result, *i); + } + + info->result = result; +} + +char * benchmark_getName(benchmark_pt benchmark) { + return (char *)BENCHMARK_NAME; +} + +static void benchmark_continue(benchmark_pt benchmark) { + benchmark->state = BENCHMARK_STATE_RUNNING; + unsigned long waitTime = 0; + while (benchmark->threadsRunning < benchmark->nrOfThreads) { + usleep(WAIT_TIME); + waitTime += WAIT_TIME; + if (waitTime > 1000 * 1000 * 2) { + printf("still waiting to stop, running threads are %i\n", + benchmark->threadsRunning); + } + } +} + +static void benchmark_interrupt(benchmark_pt benchmark) { + int i = 0; + unsigned long waitTime = 0; + if (benchmark->state == BENCHMARK_STATE_RUNNING) { + benchmark->state = BENCHMARK_STATE_INTERRUPTED; + while (benchmark->threadsRunning > 0) { + usleep(WAIT_TIME); + waitTime += WAIT_TIME; + if (waitTime > 1000 * 1000 * 2) { + printf("still waiting to stop, running threads are %i\n", + benchmark->threadsRunning); + } + } + } +} + +celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) { + pthread_mutex_lock(&benchmark->mutex); + benchmark_interrupt(benchmark); + benchmark->math = mathService; + benchmark_continue(benchmark); + pthread_mutex_unlock(&benchmark->mutex); + return CELIX_SUCCESS; +} + +celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) { + pthread_mutex_lock(&benchmark->mutex); + if (benchmark->math == mathService) { + benchmark_interrupt(benchmark); + benchmark->math = NULL; + benchmark_continue(benchmark); + } + pthread_mutex_unlock(&benchmark->mutex); + return CELIX_SUCCESS; + +} + +double benchmark_getSampleFactor(benchmark_pt benchmark) { + return SAMPLE_FACTOR; +} http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/include/service_reference_private.h ---------------------------------------------------------------------- diff --git a/framework/private/include/service_reference_private.h b/framework/private/include/service_reference_private.h index b297c14..114eae1 100644 --- a/framework/private/include/service_reference_private.h +++ b/framework/private/include/service_reference_private.h @@ -33,12 +33,17 @@ struct serviceReference { bundle_pt bundle; struct serviceRegistration * registration; + + size_t refCount; + celix_thread_mutex_t mutex; //protects refCount }; celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference); -celix_status_t serviceReference_destroy(service_reference_pt *reference); + +void serviceReference_retain(service_reference_pt ref); +void serviceReference_release(service_reference_pt ref); celix_status_t serviceReference_invalidate(service_reference_pt reference); -celix_status_t serviceRefernce_isValid(service_reference_pt reference, bool *result); +celix_status_t serviceReference_isValid(service_reference_pt reference, bool *result); #endif /* SERVICE_REFERENCE_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/include/service_registration_private.h ---------------------------------------------------------------------- diff --git a/framework/private/include/service_registration_private.h b/framework/private/include/service_registration_private.h index 8f31a14..081f996 100644 --- a/framework/private/include/service_registration_private.h +++ b/framework/private/include/service_registration_private.h @@ -51,11 +51,15 @@ struct serviceRegistration { struct service *services; int nrOfServices; + + size_t refCount; //protected by mutex }; service_registration_pt serviceRegistration_create(service_registry_pt registry, bundle_pt bundle, char * serviceName, long serviceId, void * serviceObject, properties_pt dictionary); service_registration_pt serviceRegistration_createServiceFactory(service_registry_pt registry, bundle_pt bundle, char * serviceName, long serviceId, void * serviceObject, properties_pt dictionary); -celix_status_t serviceRegistration_destroy(service_registration_pt registration); + +void serviceRegistration_retain(service_registration_pt registration); +void serviceRegistration_release(service_registration_pt registration); bool serviceRegistration_isValid(service_registration_pt registration); void serviceRegistration_invalidate(service_registration_pt registration); http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/include/service_registry_private.h ---------------------------------------------------------------------- diff --git a/framework/private/include/service_registry_private.h b/framework/private/include/service_registry_private.h index 7bda186..d89f28e 100644 --- a/framework/private/include/service_registry_private.h +++ b/framework/private/include/service_registry_private.h @@ -50,6 +50,7 @@ struct usageCount { unsigned int count; service_reference_pt reference; void * service; + service_registration_pt registration; }; typedef struct usageCount * usage_count_pt; http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/src/properties.c ---------------------------------------------------------------------- diff --git a/framework/private/src/properties.c b/framework/private/src/properties.c index 14455c4..271eed1 100644 --- a/framework/private/src/properties.c +++ b/framework/private/src/properties.c @@ -180,6 +180,28 @@ void properties_store(properties_pt properties, char * filename, char * header) } } +celix_status_t properties_copy(properties_pt properties, properties_pt *out) { + celix_status_t status = CELIX_SUCCESS; + properties_pt copy = properties_create(); + + if (copy != NULL) { + hash_map_iterator_pt iter = hashMapIterator_create(properties); + while (hashMapIterator_hasNext(iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(iter); + char *key = hashMapEntry_getKey(entry); + char *value = hashMapEntry_getValue(entry); + properties_set(copy, key, value); + } + hashMapIterator_destroy(iter); + } else { + status = CELIX_ENOMEM; + } + + if (status == CELIX_SUCCESS) { + *out = copy; + } +} + char * properties_get(properties_pt properties, char * key) { return hashMap_get(properties, key); } http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/src/service_reference.c ---------------------------------------------------------------------- diff --git a/framework/private/src/service_reference.c b/framework/private/src/service_reference.c index 528b4be..24fdc99 100644 --- a/framework/private/src/service_reference.c +++ b/framework/private/src/service_reference.c @@ -28,6 +28,7 @@ #include <constants.h> #include <stdint.h> #include <utils.h> +#include <assert.h> #include "service_reference.h" @@ -39,29 +40,53 @@ #include "bundle.h" #include "celix_log.h" -celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference) { +static void serviceReference_destroy(service_reference_pt); + +celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *out) { celix_status_t status = CELIX_SUCCESS; - *reference = malloc(sizeof(**reference)); - if (!*reference) { + service_reference_pt ref = calloc(1, sizeof(*ref)); + if (!ref) { status = CELIX_ENOMEM; } else { - - (*reference)->bundle = bundle; - (*reference)->registration = registration; + ref->bundle = bundle; + ref->registration = registration; + celixThreadMutex_create(&ref->mutex, NULL); + ref->refCount = 1; } - framework_logIfError(logger, status, NULL, "Cannot create service reference"); + if (status == CELIX_SUCCESS) { + *out = ref; + } else { + framework_logIfError(logger, status, NULL, "Cannot create service reference"); + } return status; } -celix_status_t serviceReference_destroy(service_reference_pt *reference) { - (*reference)->bundle = NULL; - (*reference)->registration = NULL; - free(*reference); - *reference = NULL; - return CELIX_SUCCESS; +void serviceReference_retain(service_reference_pt ref) { + celixThreadMutex_lock(&ref->mutex); + ref->refCount += 1; + celixThreadMutex_unlock(&ref->mutex); +} + +void serviceReference_release(service_reference_pt ref) { + celixThreadMutex_lock(&ref->mutex); + assert(ref->refCount > 0); + ref->refCount -= 1; + if (ref->refCount == 0) { + serviceReference_destroy(ref); + } else { + celixThreadMutex_unlock(&ref->mutex); + } +} + +static void serviceReference_destroy(service_reference_pt ref) { + assert(ref->refCount == 0); + celixThreadMutex_destroy(&ref->mutex); + ref->bundle = NULL; + ref->registration = NULL; + free(ref); } celix_status_t serviceReference_getBundle(service_reference_pt reference, bundle_pt *bundle) { @@ -109,7 +134,7 @@ celix_status_t serviceReference_invalidate(service_reference_pt reference) { return CELIX_SUCCESS; } -celix_status_t serviceRefernce_isValid(service_reference_pt reference, bool *result) { +celix_status_t serviceReference_isValid(service_reference_pt reference, bool *result) { (*result) = reference->registration != NULL; return CELIX_SUCCESS; } @@ -117,22 +142,8 @@ celix_status_t serviceRefernce_isValid(service_reference_pt reference, bool *res bool serviceReference_isAssignableTo(service_reference_pt reference, bundle_pt requester, char * serviceName) { bool allow = true; - bundle_pt provider = reference->bundle; - if (requester == provider) { - return allow; - } -// wire_pt providerWire = module_getWire(bundle_getCurrentModule(provider), serviceName); -// wire_pt requesterWire = module_getWire(bundle_getCurrentModule(requester), serviceName); -// -// if (providerWire == NULL && requesterWire != NULL) { -// allow = (bundle_getCurrentModule(provider) == wire_getExporter(requesterWire)); -// } else if (providerWire != NULL && requesterWire != NULL) { -// allow = (wire_getExporter(providerWire) == wire_getExporter(requesterWire)); -// } else if (providerWire != NULL && requesterWire == NULL) { -// allow = (wire_getExporter(providerWire) == bundle_getCurrentModule(requester)); -// } else { -// allow = false; -// } + /*NOTE for now always true. It would be nice to be able to do somechecks if the services are really assignable. + */ return allow; }
