Assume I have a function calc_sum() and I want to measure its execution time. I have a callback function info_callback() which prints a message and calculates execution time, it takes void pointer as parameter. I want to cast void* to struct timeval * to retrieve start/end of execution time and calculate the difference, but I can't understand how to pass the pointer to array struct timeval * so that I can access its elements from within info_callback() function.
Whatever I try, I get segmentation fault...
How should I pass and cast pointers to get it work?
EDIT: fixed error in code as Andy Schweig suggested
#include <stdio.h>
#include <sys/time.h>
void calc_sum(int a, int b)
{
int k = a + b;
printf("sum = %d\n", k);
}
void info_callback(const char *msg, void *client_data)
{
struct timeval *t = (struct timeval *) client_data;
double time = (t[1].tv_sec - t[0].tv_sec) * 1000.0; // !!!SEGMENTATION FAULT!!!
time += (t[1].tv_usec - t[0].tv_usec) / 1000.0; //
printf("[TIME] %s: %f, ms", msg, time);
}
int main(int argc, char *argv[])
{
struct timeval t1, t2;
gettimeofday(&t1, NULL);
calc_sum(2, 3);
gettimeofday(&t2, NULL);
struct timeval * tr = (struct timeval*) malloc(2 * sizeof(struct timeval));
tr[0] = t1;
tr[1] = t2;
double time = (tr[1].tv_sec - tr[0].tv_sec) * 1000.0; // sec to ms
time += (tr[1].tv_usec - tr[0].tv_usec) / 1000.0; // us to ms
printf("time = %f, ms\n", time);
info_callback("Execution time", tr);
free(tr);
}
You should pass tr to info_callback instead of &tr. tr points to the array you allocated; &tr is a pointer to the pointer tr.
By the way, any particular reason for using void * instead of the actual type? If you had used the actual type, the compiler would have flagged this.
Related
having some trouble finding out the syntax around returning a vector from a pthread function. Here's currently what I have:
typedef struct vectorData {
vector v1;
vector v2;
} vectorData;
void *vectorAddThread(void *arg) {
vectorData *data = (vectorData *)arg;
vector v1 = data->v1;
vector v2 = data->v2;
vector result = {v1->x + v2->x, v1->y + v2->y, v1->z + v2->z};
return (void*) result;
}
I'm getting errors on the last two lines about the return result, and the the adding part. Thanks
You can't convert a struct to a void * pointer. You need dynamically allocate a vector in your case with malloc, and return the pointer.
vector *result = malloc(sizeof(vector));
result->x = ?;
result->y = ?;
result->z = ?;
return (void *)result;
Now that would solve the issue of returning a struct from a function that returns void *. But if you're using pthreads you shouldn't be returning objects from them, you need to pass the vector to it as user data in arg.
This is probably easiest:
typedef struct vectorData {
vector v1;
vector v2;
vector result;
} vectorData;
Saves messing about with dubious thread-stack vars, mallocs etc. and ties the result output directly to the inputs.
The thread start function in pthread library returns a pointer to void. Can return any pointer type by type-casting it to (void *). The return value can be accessed by pthread_join(3).
However, a vector needs the type of element information also. Not sure if type-casting it to (void *) and accessing it again will work fine. Using it as an element of structure seems better.
In the following example, I am returning a pointer to structure from the thread start function. The structure contains a vector and two character arrays. You can change it according to your requirement. I am using two pointers to show that data is copied on the variable used for pthread_join(3).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <vector>
void *functionPthread(void *);
struct retStruct
{
std::vector<int> vecNumber;
char name[20];
char city[20];
};
struct retStruct *r2;
struct retStruct *r1;
int main()
{
int rc, i;
pthread_t th;
r2 = (retStruct*) malloc(sizeof(retStruct));
memset(r2, '\0', sizeof(r2));
if(rc = pthread_create(&th, NULL, &functionPthread, NULL))
{
printf("Thread creation failed, return code %d, errno %d", rc, errno);
}
pthread_join(th, (void**)&r2);
for(i = 0; i < r2->vecNumber.size(); i++)
printf("Vectore element at index %d = %d\n", i, r2->vecNumber.at(i));
printf("Name: %s, City: %s, Vector Number: %d\n", r2->name, r2->city, r2->vecNumber.front());
free(r1);
free(r2);
return 0;
}
void *functionPthread(void *)
{
r1 = (retStruct*) malloc(sizeof(retStruct));
memset(r1, '\0', sizeof(r1));
strcpy(r1->name, "xxxx");
strcpy(r1->city, "yyyy");
r1->vecNumber.push_back(11);
r1->vecNumber.push_back(12);
return r1;
}
My following code gives segmentation fault: 11 only when I add the clock() function to calculate the time elapsed (When I comment clock(), I get results with no issues!!! ):
typedef struct heap_strct *Sort;
struct heap_strct {
int count;
int size;
int *queue;
};
int main() {
time_t start = clock();
Sort h; // Sort is a structure
initi(h);
parse(h);
time_t end = clock();
double time_elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("Time = %f", time_elapsed);
}
I am using #include <time.h> but I don't know why such a fault appears! Kindly, can someone tell me why?
You pass an uninitialized pointer to function initi(). If this function modifies the structure, you invoke undefined behavior.
It is a very bad habit to hide pointers behind typedefs. The comment is completely misleading: Sort is not a structure!
Define a structure directly and pass its address:
#include <time.h>
struct heap_strct {
int count;
int size;
int *queue;
};
int main(void) {
clock_t start = clock();
struct heap_strct h; // h is a structure for real now!
initi(&h);
parse(&h);
time_t end = clock();
double time_elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("Time = %f\n", time_elapsed);
return 0;
}
clock() is a proven library function and will not cause a segfault.
You pass a pointer h to initi but there is no storage for h allocated. Then you pass the same pointer to parse. But there still is no storage for the structure!
When you comment clock() out, the call is not made so the stack is not changed. On the stack is also h, an uninitialized local variable.
The function displayTimeDifference is not working properly; the issue is that the printf statement is failing. After Googling the format of the printf statement when using a timeval is correct. Not sure why I can't print out the value of the timeval. I'm not getting any system errors from gettimeofday().
#include <sys/time.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
struct timeval *timeBefore;
struct timeval *timeAfter;
char * Buffer;
double malloctest(const int, const int, const int);
double calloctest(const int, const int, const int);
double allocatest(const int, const int, const int);
void displayTimeDifference();
int main(int argc, char **argv)
{
malloctest(3072, 10, 10);
return 0;
}
double malloctest(const int objectsize, const int numobjects, const int numtests)
{
int i;
int retVal;
for (i = 1; i < numtests; i++) {
if ((retVal = gettimeofday(timeBefore, NULL)) != 0) {
printf("ERROR: gettimeofday failed with code: %d\n", retVal);
}
Buffer = (char*)malloc(objectsize * sizeof(char));
if ((retVal = gettimeofday(timeAfter, NULL)) != 0) {
printf("ERROR: gettimeofday failed with code: %d\n", retVal);
}
displayTimeDifference();
}
return 0.0;
}
void displayTimeDifference()
{
printf("Time in microseconds: %ld microseconds\n", (timeAfter->tv_sec - timeBefore->tv_sec));
}
gettimeofday needs a valid pointer to struct timeval, where it can save the informations, you call it with a NULL pointer.
you should change
struct timeval *timeBefore;
struct timeval *timeAfter;
to
struct timeval timeBefore;
struct timeval timeAfter;
and the calls to gettimeofday(&timeBefore, NULL) and gettimeofday(&timeAfter, NULL). You check the return value of this function and print something, but your program continues as it was successfully.
Also
printf("Time in microseconds: %ld microseconds\n", (timeAfter->tv_sec - timeBefore->tv_sec));
to
printf("Time in seconds: %ld microseconds\n", (timeAfter.tv_sec - timeBefore.tv_sec));.
You are only calculating the seconds, not the microseconds.
Another possibility is to malloc the memory for the pointer, but that is not really necessary.
As already said in another answer you have wrongly declared the struct timeval as pointers.
I share my timing macros:
#define START_TIMER(begin) gettimeofday(&begin, NULL) // ;
#define END_TIMER(end) gettimeofday(&end, NULL) // ;
//get the total number of sec:
#define ELAPSED_TIME(elapsed, begin, end) \
elapsed = (end.tv_sec - begin.tv_sec) \
+ ((end.tv_usec - begin.tv_usec)/1000000.0) // ;
Where you have to define the variables:
struct timeval begin, end;
double elapsed;
I found here, on SO, a simple function to measure the execution time of a function in C:
#include <stdio.h>
#include <stdint.h>
#include <time.h>
int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
int main(int argc, char **argv)
{
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
// Some code I am interested in measuring
clock_gettime(CLOCK_MONOTONIC, &end);
uint64_t timeElapsed = timespecDiff(&end, &start);
}
Now I would like to use it to measure some cryptographic function executions. For now on, Im interesting only in Openssl and Crypto++ (but would like to extend the list with other libraries).
In C++ I would use templates for this, but how about C? Let's say, I have 2 functions:
void md4_openssl(...); and void md4_cryptopp(...); where all the parameters setups (keys, buffers, ...) are INSIDE those functions. Now, how can I make my measruring function more "generic"? In the way that something like this would be possible:
void measureTime()
{
function(); // could be md4_openssl or md4_cryptopp
}
Of course, I would use opnessl if installed, but if it is not, it will call cryptopp function
The obvious way is a pass a pointer to function to measureTime():
uint64_t measureTime(void (*fp)(void)) {
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
fp(); // Call the function you want to measure
clock_gettime(CLOCK_MONOTONIC, &end);
return timespecDiff(&end, &start);
}
void measure_ssl(void) {
md4_openssl(1, 2, 3, whatever); // Setup and call however you need to
}
void measure_crypt(void) {
md4_cryptopp(1, 2, 3, whatever); // Setup and call however you need to
}
int main(void) {
uint64_t t1 = measureTime(measure_ssl);
uint64_t t2 = measureTime(measure_crypt);
// Do something with t1 and t2
return 0;
}
EDIT: In response to your comment, any function pointer you pass to a function must have the signature matching the parameter. If you need to call functions which have different signatures, then you need to wrap them as the above code does.
If your wrapper function can take care of the parameters, then you can just use the above code without modification. In other words, measure_ssl() can call md4_openssl(1, 2, 3, "more", "args") and measure_crypt() can call md4_cryptopp(5.4, "different", ARGS) or whatever.
If you do need to actually provide the arguments to measureTime(), you'll have to pass information to your wrapper functions and have them do some interpretation. If each function took, say, one pointer, but of a different type, you could just pass a single void * and pass it on.
If the arguments can be completely different and unpredictable, then the simplest way to do it is create a struct and pass the address of that, for instance:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <time.h>
void func1(int a, int b, int c) {
printf("Let's count to %d, %d and %d!\n", a, b, c);
}
struct func1_params {
int a;
int b;
int c;
};
void func2(double d, const char * c) {
printf("There are %f %ss\n", d, c);
}
struct func2_params {
double d;
const char * c;
};
void func1_wrap(void * params) {
struct func1_params * p = params;
func1(p->a, p->b, p->c);
}
void func2_wrap(void * params) {
struct func2_params * p = params;
func2(p->d, p->c);
}
int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p) {
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
uint64_t measureTime(void (*fp)(void *), void * params) {
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
fp(params);
clock_gettime(CLOCK_MONOTONIC, &end);
return timespecDiff(&end, &start);
}
int main(void) {
struct func1_params p1 = {1, 2, 3};
uint64_t t1 = measureTime(func1_wrap, &p1);
struct func2_params p2 = {3.14159, "pie"};
uint64_t t2 = measureTime(func2_wrap, &p2);
printf("First func took time %" PRIu64 " units.\n", t1);
printf("Second func took time %" PRIu64 " units.\n", t2);
return 0;
}
This is generic, in that measureTime() doesn't need to know anything about the functions you're calling, or anything about the struct. You could compile that into a library, and then much later write, say, func1_wrap() and struct func1_params and pass them in. You can measure the time of any function you like just by writing a struct to contain the arguments and a wrapper function of type void (*)(void *) to accept a pointer to that struct and pass the members as arguments to the function you're interested in.
In the above code, I've provided the definitions of func1() and func2() to provide a complete working example, but you can think of these as your md4_openssl() and md4_cryptopp() functions instead, and have your wrapper functions call those.
I am trying to create a function that compare two timestamps, if the first timestamp is earlier than the second one, the function will return -1; if equal, return 0; if later, return 1;
Below is my code, however, it does not work and throws segmentation fault (core dumped) error when I run it:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
typedef struct timeval timevalue;
int compare_time_stamps(timevalue *a, timevalue *b)
{
int cmp = timercmp(a, b, >);
if (cmp > 0)
return 1; /* a is greater than b */
else
{
cmp = timercmp(a, b, ==);
if (cmp > 0)
return 0; /* a is equal to b */
else
return -1; /* a is less than b */
}
}
int main()
{
timevalue *start, *end;
gettimeofday(start, NULL);
int i;
for (i = 0; i < 1000000; i++);
gettimeofday(end, NULL);
int cmp = compare_time_stamps(start, end);
printf("comparison result is %d\n", cmp);
return 0;
}
This being said, if I do not start with timevalue *, everything works just fine, see the working code below:
typedef struct timeval timevalue;
int compare_time_stamps(timevalue a, timevalue b)
{
int cmp = timercmp(&a, &b, >);
if (cmp > 0)
return 1; /* a is greater than b */
else
{
cmp = timercmp(&a, &b, ==);
if (cmp > 0)
return 0; /* a is equal to b */
else
return -1; /* a is less than b */
}
}
int main()
{
timevalue start, end;
gettimeofday(&start, NULL);
int i;
for (i = 0; i < 1000000; i++);
gettimeofday(&end, NULL);
int cmp = compare_time_stamps(start, end);
printf("the comparison result is %d\n", cmp);
return 0;
}
What makes the difference between these two approaches? thanks
timevalue start, end;
when you do this, you are allocating space for the struct timeval, which you have called
typedef struct timeval timevalue;
so you are actually allocating the space for the two structures in you current stack frame.
when you do timevalue *start, *end; you are only allocating two pointers to the struct timeval but no memory has been allocated to the struct timeval you would have to use malloc and allocate space.
start = malloc(sizeof(timevalue));
end = malloc(sizeof(timevalue));
also at the end of the function you have to free the malloced memory
printf("comparison result is %d\n", cmp);
free(start);
free(end);
return 0;
}
in C when you define a pointer(int *a) its your job to make sure it points to valid memory. some reading up on pointers should do.
When you use timevalue*, start is a pointer with no memory allocated to it. It will be having garbage value. Hence you get a segmentation fault.
When you use timevalue, the memory is allocated to the start variable and the time value is stored there.
the macro timbal is a struct like this:
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
so you need to allocate memory when you use "*".