Showing posts with label C. Show all posts
Showing posts with label C. Show all posts

Monday, October 28, 2013

Clock in Wind32

   1: // GetTickCount accuracy is about 10~15ms
   2: DWORD start = GetTickCount();
   3: PRINT("Time used for  :%ld ms ", GetTickCount() - start);
   4:  
   5: // If need higher accuracy
   6: LARGE_INTEGER lp_s, lp_e, lp;
   7: QueryPerformanceCounter(&lp_s);
   8:    // measured function here ...
   9: QueryPerformanceCounter(&lp_e);
  10: QueryPerformanceFrequency(&lp);
  11: PRINT("Time used for func :%I64d ticks ", lp_e.QuadPart - lp_s.QuadPart);
  12: PRINT("Time used for func :%f sec ", (float)(lp_e.QuadPart - lp_s.QuadPart) / (float)lp.QuadPart);

Monday, February 08, 2010

Function pointers

Here is an example, we have a structure named Slice, the function like ‘get_direct_motion_vectors’ should really be put inside this structure. So we can use ‘Slice->get_direct_motion_vectors(…)’instead of just call that function. So put a function pointer inside the structure is a good one:
typedef struct slice
{
    int picture_id;
    void (*get_direct_motion_vectors)    (Macroblock *currMB);
    ...
}Slice;

// Usage: 

(*currSlice)->get_direct_motion_vector = Get_MV;

// where ‘Get_MV’ is defined in another .h file: mv_search.h
extern void Get_MV(Macroblock *currMB);

// and it is implemented in .c file: mv_search.c
void Get_MV(Macroblock *currMB) { . . .}

[update 2/19/2012] Garmin asked
The function pointer inside the structure make C look like Object Oriented.
Because C does not support classes, structs are used.
Because structs do not support methods, function pointers are used
Comparing Objects: C++ /C:

class algo{
public:
// methods
   int method1(int param);
   int method2(int param);
// attributes
   int attr1;
   int attr2;
}

typedef struct {
// methods
   int (*method1) (int param);
   int (*method2) (int param);
// attributes
   int attr1;
   int attr2;
} algo;

Monday, February 01, 2010

Garbage in C

p = malloc(...);
q = malloc(...);
/* free (p); */

p = q;


p points to one memory block and q points to another.

After q is assigned to p, both point the the second memory block. There are no pointers to the first block. This memory block cannot be accessible to program, it is called ‘garbage’. A program that leaves garbage behind has memory leak. C doesn’t have garbage collector.

You can use ‘free(p)’ to release the memory block that p points to.

After you released the memory block, if you attempt to access or modify this deallocated memory block, it causes undefined behavior.

Thursday, January 28, 2010

Trivia of Preprocessor

The preprocessor's role in the compilation process is:
C program -> (Preprocessor) -> modified C program -> (Compiler) -> Object code.
The preporcessor executes the directives and remove them in the process (make those lines empty), and replace the #define directives wherever they appeared later in the file.

Three types of preprocessing directives:
  1. Macro definition: #define, #undef
  2. File inclusion: #include
  3. Condition compilation: #if, #ifdef, #ifndef, #elif, #else, #endif. (others include #error, #line, #progma)
#undef N : removes the current definition of macro N. If N has not been defined, #undef has no effect. Usually this is used to give a new definition to existing macro.

Several predefined Macros:
  • __LINE__ : line number of file being compiled
  • __FILE__ : name of file being compiled
  • __DATA__ : mm dd yyyy
  • __TIME__ : hh:mm:ss
#if defined DEBUG // same as #if defined (DEBUG)
...
#endif
Since 'defined' tests only where DEBUG is defined or not, it is not necessary to give DEBUG a value. Just use: #define DEBUG

#ifdef DEBUG // equivalent to #if defined DEBUG
#endif

#ifndef DEBUG // equivalent to #if !defined DEBUG
-------------------
#ifdef WIN32
...
#elif defined MAC
...
#elif defined LINUX
...
#else
#error no operation system chosen
#end

Use following to condition out the block of codes:
#if 0
...
#endif
Reminder: those block of codes are not completely ignored. Comments are processed before preprocessing. If you have unterminated comments between #if 0, #endif, you still get compile error (like you have /*abcdefg ). Unpaired quote could give you a warning.

#error message : usually the compiler will terminate immediately without trying to find other errors
#if MAX < 10000
# // it is legal to use null directive
#error max value is too small
#
#endif

Friday, December 04, 2009

Bit manipulation and Overlap structure in embedded system

Testing bits:

if (*pStatus & 0x08)

{…}’

(0x4C) 0100 1100 & 0000 1000 (0x08) = 0000 1000

Setting bits:

*pStatus |= 0x10

(0x4C) 0100 1100 | 0001 0000 (0x10) = 0101 1100

Clearing bits:

*pStatus &= ~(0x04)

(0x5C) 0101 1100 & 1111 1011 = 0101 1000

Toggling bits:

*pStatus ^= 0x80

(0x58) 0101 1000 ^ 1000 0000 = 1101 1000

Above is the code to toggle bit 7.

For write-only register, you cannot use ‘ &=, |= …”. A copy of the register’s contents should be held in a variable in RAM to maintain the current state of the write-only register.

status_tmp = STATUS;
*pStatus_writeonly = status_tmp;

/* when you want to change the content of register: */
status_tmp |= STATUS_ENABLE;
*pStatus_writeonly = status_tmp;

Struct Overlays

Benefits of struct overlays are that you can read/write through a pointer to the struct, and the compiler does the address construction at compile time.

typedef struct

{

uint16_t count; /* Offset 0x00 */

uint16_t maxCount; /* Offset 0x02 */

uint16_t _reserved1; /* Offset 0x04 */

uint16_t control; /* Offset 0x06 */

} volatile timer_t;

timer_t *pTimer = (timer_t *)(0xABCD0123);

Monday, November 09, 2009

The worst embedded codes

A very good presentation talking about embedded codes. link (pdf)

Friday, May 15, 2009

Several Trivia about Bit Operation

Shift and division: Bit right/left shift to implement arithmetic division and multiplication by a power of 2. It works with unsigned types, and signed types for left shift. Division with signed types rounds toward 0, but right shift rounds to negative infinite.

int a, b, c;
a = -1;
b = a >> 1; // b is -1;
c = a / 2; // c is 0;

In two’s complement, zero is not the only number that is equal to its negative, same happens to the value with just the highest bit set

if (x < 0)  x = -x;
// assume x is always positive
// but is it wrong
bitshift_negative

A shift by more than BITS_PER_LONG-1 is undefined by the C-standard.

int foo (int k)
{
int t = ABC >> (BIT_PER_INT - k);
return t; // when k == 0, undefined
}
if (k == 0) t = 0; // add this before return in foo

Thursday, January 22, 2009

Semaphore basic

Semaphores can be thought of as simple counters that indicate the status of a resource. The usage of this semaphore variable is simple. If counter is greater that 0, then the resource is available, and if the counter is 0 or less, then that resource is busy or being used by someone else. This simple mechanism helps in synchronizing multithreaded and multiprocess based applications. [updated:3/5/2010]

A semaphore is as an object with an integer value that we can manipulate with two routines (sem_wait() and sem_post() in POSIX standard). Because the initial value of the semaphore determines its behavior, before calling any other routine to interact with the semaphore, we must first initialize it to some value, as this code below does:

sem_wait() will either return right away (because the value of the semaphore was 1 or higher when we called sem_wait()), or it will cause the caller to suspend execution waiting for a subsequent post. Of course, multiple calling threads may call into sem_wait(), and thus all be queued waiting to be woken. Once woken, the waiting thread will then decrement the value of the semaphore and return to the user.

sem_post() does not ever suspend the caller. Rather, it simply increments the value of the semaphore and then, if there is a thread waiting to be woken, wakes 1 of them up.

#include <semaphore.h>
sem_t s;
sem_init(&s, 0, 1); // replace 1 with X
...
// lock the resource
int sem_wait(sem_t *s) {
wait until value of semaphore s is > 0
decrement the value of semaphore s by 1
}
... do some stuff

// release the resource 
int sem_post(sem_t *s) {
increment the value of semaphore s by 1
if there are 1 or more threads waiting, wake 1
}

Look at the following code, the *producer/consumer* problem:

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

#define MAX 1 //2
sem_t empty;
sem_t full;
int loops = 100;
int buffer[MAX];
int fill = 0;
int use = 0;

void put(int value) {
buffer[fill] = value; // line F1
fill = (fill + 1) % MAX; // line F2
}
int get() {
int tmp = buffer[use]; // line G1
use = (use + 1) % MAX; // line G2
return tmp;
}
void *producer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
sem_wait(&empty); // line P1
put(i); // line P2
sem_post(&full); // line P3
}
}
void *consumer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
sem_wait(&full); // line C1
int tmp = get(); // line C2
sem_post(&empty); // line C3
printf("%d\n", tmp);
}
}

int main(int argc, char *argv[])
{
pthread_t pid, cid, pid2;
sem_init(&empty, 0, MAX); // MAX buffers are empty to begin with...
sem_init(&full, 0, 0); // ... and 0 are full
pthread_create(&pid, NULL, producer, NULL);
//pthread_create(&pid2, NULL, producer, NULL);
pthread_create(&cid, NULL, consumer, NULL);
pthread_join(pid, NULL);
//pthread_join(pid2, NULL);
pthread_join(cid, NULL);
return 0;
}

Let MAX=1 first. Assume the consumer gets to run first. Thus, the consumer will hit line C1 in the figure above, calling sem_wait(&full). Because full was initialized to the value 0, the call will block the consumer and wait for another thread to call sem_post() on the semaphore, as desired.

Let's say the producer then runs. It will hit line P1, calling sem_wait(&empty). Unlike the consumer, the producer will continue through this line, because empty was initialized to the value MAX (in this case, 1). Thus, empty will be decremented to 0 and the producer will put a data value into the first entry of buffer (line P2). The producer will then continue on to P3 and call sem_post(&full), changing the value of the full semaphore from 0 to 1 and waking the consumer (e.g., move it from blocked to ready).

In this case, one of two things could happen. If the producer continues to run, it will loop around and hit line P1 again. This time, however, it would block, as the empty semaphore's value is 0. If the producer instead was interrupted and the consumer began to run, it would call sem_wait(&full) (line C1) and find that the buffer was indeed full and thus consume it. In either case, we achieve the desired behavior.

When MAX > 1, and we have multiple producers and consumers (uncomments pid2). There is problem. Imagine two producers both calling into put() at roughly the same time. Assume producer 1 gets to run first, and just starts to fill the first buffer entry (fill = 0 @ line F1). Before the producer gets a chance to increment the fill counter to 1, it is interrupted. Producer 2 starts to run, and at line F1 it also puts its data into the 0th element of buffer, which means that the old data there is overwritten!

What we've forgotten here is *mutual exclusion*. The filling of a buffer and incrementing of the index into the buffer is a *critical section*, and thus must be guarded carefully. So let's use our friend the binary semaphore and add some locks. Here is our first try:

sem_t empty;
sem_t full;
sem_t mutex;

void *producer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
sem_wait(&mutex); // line P0 (NEW LINE)
sem_wait(&empty); // line P1
put(i); // line P2
sem_post(&full); // line P3
sem_post(&mutex); // line P4 (NEW LINE)
}
}

void *consumer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
sem_wait(&mutex); // line C0 (NEW LINE)
sem_wait(&full); // line C1
int tmp = get(); // line C2
sem_post(&empty); // line C3
sem_post(&mutex); // line C4 (NEW LINE)
printf("%d\n", tmp);
}
}

int main(int argc, char *argv[]) {
// ...
sem_init(&empty, 0, MAX); // MAX buffers are empty to begin with...
sem_init(&full, 0, 0); // ... and 0 are full
sem_init(&mutex, 0, 1); // mutex = 1 because it is a lock (NEW LINE)
// ...
}

Deadlock happens here.
Imagine two threads, one producer and one consumer. The consumer gets to run first. It acquires the mutex (line C0), and then calls sem_wait() on the full semaphore (line C1); because there is no data yet, this call causes the consumer to block and thus yield the CPU; importantly, though, the consumer still holds the lock.

A producer then runs. It has data to produce and if it were able to run, it would be able to wake the consumer thread and all would be good. Unfortunately, the first thing it does is call sem_wait on the binary mutex semaphore (line P0). The lock is already held. Hence, the producer is now stuck waiting too.

There is a simple cycle here. The consumer holds the mutex and is waiting for the someone to signal full. The producer could *signal* full but is waiting for the mutex. Thus, the producer and consumer are each stuck waiting for each other: a classic deadlock.
Solution:

void *producer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
sem_wait(&empty); // line P1
sem_wait(&mutex); // line P1.5 (MOVED THE MUTEX TO HERE ...)
put(i); // line P2
sem_post(&mutex); // line P2.5 (... AND TO HERE)
sem_post(&full); // line P3
}
}

void *consumer(void *arg) {
int i;
for (i = 0; i < loops; i++) {
sem_wait(&full); // line C1
sem_wait(&mutex); // line C1.5 (MOVED THE MUTEX TO HERE ...)
int tmp = get(); // line C2
sem_post(&mutex); // line C2.5 (... AND TO HERE)
sem_post(&empty); // line C3
printf("%d\n", tmp);
}
}
all are from following class, a free book about semaphore here, and an article comparing mutex, semaphore here.
--
A semaphore is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count - the count of keys - is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue.

A mutex is a key to a toilet. One person can have the key - occupy the toilet - at the time. When finished, the person gives (frees) the key to the next person in the queue. [quote from following link, update:3/5/2010]

Tuesday, January 20, 2009

"this" pointer

The this pointer is a pointer accessible only within the nonstatic member functions of a class, struct, or union type. It points to the object for which the member function is called. Static member functions do not have a this pointer. An object's this pointer is not part of the object itself; it is not reflected in the result of a sizeof statement on the object.

  • this pointer stores the address of the class instance, to enable pointer access of the members to the member functions of the class.
  • this pointer is not counted for calculating the size of the object.
  • this pointers are not accessible for static member functions.
  • this pointers are not modifiable.
void Date::setMonth(int mn)
{
month = mn; // These three statements
this->month = mn; // are equivalent
(*this).month = mn;
}
The this pointer is passed as a hidden argument to all nonstatic member function calls and is available as a local variable within the body of all nonstatic functions. The type of the this pointer for a member function of a class type X, is X* const. If the member function is declared with the const qualifier, the type of the this pointer for that member function for class X, is const X* const.

The following two are the same:

struct X {
private:
int len;
char *ptr;
public:
int GetLen() {
return len;
}
char * GetPtr() {
return ptr;
}
X& Set(char *);
};

X& X::Set(char *pc) {
len = strlen(pc);
ptr = new char[len];
strcpy(ptr, pc);
return *this;
}

-

struct X {
private:
int len;
char *ptr;
public:
int GetLen (X* const THIS) {
return THIS->len;
}
char * GetPtr (X* const THIS) {
return THIS->ptr;
}
X& Set(X* const, char *);
};

X& X::Set(X* const THIS, char *pc) {
THIS->len = strlen(pc);
THIS->ptr = new char[THIS->len];
strcpy(THIS->ptr, pc);
return *THIS;
}

Wednesday, October 01, 2008

Deadlock

Resources.

  • Physical resources: printers, type drivers, memory space, CPU cycles...
  • logical resources: files, semaphores, monitors

A deadlock situation can arise if the following 4 conditions hold simultaneously:

  1. Mutual exclusion. At least one resource is held in a nonsharable mode. If another process requests that resource, the requesting process must be delayed until the resource is released. For example, thread1 wants to acquire the mutex lock in the order of (1st mutex, 2nd mutex), while thread2 wants to acquire the mutex in the order (2nd mutex, 1st mutex). Deadlock is possible if thread1 acquires 1st mutex while thread2 acquires 2nd mutex. [prevention:] the mutual-exclusion condition must hold for nonsharable resources. (printer cannot be simultaneously shared by several processes)
  2. Hold and wait. A process holds at least one resource and waiting to acquire additional resources that are currently being held by other processes. [prevention:] Guarantee that, whenever a process requests a resource, it does not hold any other resources. Use different protocols.
  3. No preemption. A resource can be released only voluntarily by the process holding it, after that process has completed it task. [prevention:] if a process is hold some resources and requests another resource that cannot be immediately allocated, then all resources currently being held are preempted(implicitly released)
  4. circle wait. P0 is waiting for resource held by P1, P1 is waiting for a resource held by P2, ..., Pn is waiting for a resource held by P0. [prevention:] use a order of all resource types and to require that each process requests resources in an increasing order. 

Deadlock can be solved with one of following ways:

  • We can use a protocol to prevent or avoid deadlocks, ensuring the system will never enter a deadlock state.
  • All the system to enter a deadlock state, delete it and recover.
  • Ignore the problem totally and pretend the deadlocks never occur.

The last one is used by most systems. It is up to developers to write programs to handle deadlocks.

Thursday, September 25, 2008

Volatile variable

It may be modified externally from the declaring variable (object). It tells the compiler not to cache this variable in a register but instead to read the value of the variable from memory each and every time the variable is used.
Variables declared to be volatile will not be optimized by the compiler because the compiler must assume that their values can change at any time.
volatile int a = 0;
while (!a)
{
...
}

The value 'int a' is read from memory for each loop iteration. If volatile was not specified then it is likely that the compiler would generate optimized code which would read the value of the 'int a' once, temporarily store this in a register and then use the register copy during each iteration. With 'volatile', 'a' could be changed in another thread.
Examples of where volatile is often used:
compiler will not optimized 'int a'. If compile does optimization, it finds (a!=0) is always TRUE. The compile may totally remove this line. Each time the value is to be read, the value should be read directly from memory/register.
some above contents are from following link, also check wiki example
The above code (main thread with volatile, and another thread to change it). It works in debug mode, but 'a' always equals to 0 in release mode? ( i didn't get it)

[updated on Nov. 30, 09, from embedded.om]
1. can a parameter be both volatile and constant?
Yes, a read-only status register, it changes unexpectedly and you should not attempt to modify it

2. can a pointer be volatile?
yes, example: an interruption service routine modifies the pointer to a buffer.

Examples of volatile variables are:
  • Hardware registers in peripherals (for example, status registers)
  • Non-automatic variables referenced within an interrupt service routine
  • Variables shared by multiple tasks in a multi-threaded application
A good article is here

[update:12/4/09:]
Note: the individual fields of a struct, as well as the entire struct can be declared volatile.
[update: 2/28/2013]
It tells the compiler, don't optimize this part.

Tuesday, June 10, 2008

String

char *s1 = "abcde";
char s2[] = "abcde";
char const *s3 = "abcde";
char *const s4 = "abcde";
char s5[] = {'a', 'b', 'c', 'd'};
char s6[11] = "abcde";
char s7[] = {'\0', 'a', 'b'};
char s8[] = {'a', 'b', '\0'};
char s9[11];
printf("%d %d %d %d %d %d %d %d\n",
sizeof(*s1),// 1
sizeof(s1), // 4
sizeof(s2), // 6
sizeof(s5), // 4
sizeof(s6), // 11
sizeof(s7), // 3
sizeof(s8), // 3
sizeof(s9));// 11
printf("%d %d %d %d %d %d %d",
strlen(s1), // 5
strlen(s2), // 5
strlen(s5), // random
strlen(s6), // 5
strlen(s7), // 0
strlen(s8), // 2
strlen(s9));// random

s1[0] = 'f'; // run-time error
s2[0] = 'f'; // OK
s3[0] = 'f'; // compile-time error
*s3 = 'f'; // compile-time error
s3 = "kaf"; // OK
s4[0] = 'f'; // run-time error
s4 = "kaf"; // compile-time error
s5[0] = 'f'; // OK

Monday, April 28, 2008

enumeration variables vs. preprocessor #define

Functionality Enum #define
Numeric values assigned automatically? Yes No
Can the debugger display the symbolic values? Yes No
Obey block scope?  Yes No
Control over the size of the variables? No No

 

Also check the former post about enum

3 sum problem 3sum

find 3 numbers in one array [1...n] to make a+b=c. By by O(n^2).
sort the array first to get nums[], then

int threeSUM(int *nums, int size)
{
int i, j, k, result;
for (i = 0; i < size; i++)
{
j = 0;
k = size - 1;
while ( j < k )
{
result = nums[j] + nums[k] - nums[i];
if ((result < 0) || (i == j))
j++;
else if ((result > 0) || (i == k))
k--;
else
return 1;
}
}
return 0;
}

Sunday, April 27, 2008

Unions in C++

  1. Default access to a union is public, it can contain member functions and member data
  2. It can’t have a static data members or a member of reference type.
  3. It cannot have virtual functions
  4. it cannot be used as base class nor it can have base class
  5. An object of a class with a construct or a destructor or a user-defined assignment operator cannot be a member of a union [from openasthra]

Pass by value/address

If the declaration of argument matches the declaration of the formal parameter, then the argument is passed by value.

void f (char * a)
{
   a++;
}
int main (void)
{
  char *a = "abc";
  f(a);
  puts (a);
  return 0;
}

It's pass by value.  You are passing the value of the pointer a. So you get 'abc' instead of 'bc'. If you want to get 'bc', use: void f (char * &a)

Thursday, April 24, 2008

allowed in C, but not in C++?

Followings are from Internet source (openasthra.com). Some are interesting and I didn't notice before:

  1. sizeof (’1′) == sizeof (int) in C; but it is sizeof (char) in C++. So we get the result 4 and 1 with compiler gcc and g++, respectively.
  2. Usually you should not use *alloc()/free() in C++, but they are the only such functions in C.
  3. Functions need not be prototyped in C, but it is a must in C++.
  4. struct a {  
             struct b {
                    int a; 
              };
    };
    struct b b; /*allowed in C, but not in C++ */
    not quite sure this one, but it has error in g++ compiler(error: aggregate 'b b' has incomplete type and cannot be defined. With following codes:
    sturct a {
            int a;
    }
    struct a a;
    some compilers are OK, some will report error.
  5. const int b = 1; /* allowed in C and C++ */
    const int a ;      /* allowed in C, not in C++ */
  6. global variables can be defined more than once in C, not in C++
    int a; /* works in C, C++ */
    int a = 10 ; /* works in C, not in C++ */
    int main()
    {...}
  7. const a; /* equivalent to const in a; in C, illegal in C++ */
  8. char s[7] = "1234567"; /* allowed in C, error in C++ */
  9. K&R style function definitions are not allowed in C++, such as:
    void foo(a)
    int a;
    {...}

 

sizeof is an operator, not a function

To calculate the size of an object, we need the type information. This type information is available only at compile time. So no need to do it at run time.

How can it be a function when the operand is a type, not an expression.

Wednesday, April 23, 2008

Find the min, max value with recursive method

void minmax(int a[], int n, int *min_ptr, int *max_ptr)
{
int min1, max1, min2, max2;

if (n == 2)
if (a[0] < a[1]) {
*min_ptr = a[0];
*max_ptr = a[1];
}
else {
*min_ptr = a[1];
*max_ptr = a[0];
}
else {
minmax(a, n/2, &min1, &max1);
minmax(a + n/2, n/2, &min2, &max2);
if (min1 < min2)
*min_ptr = min1;
else
*min_ptr = min2;
if (max1 < max2)
*max_ptr = max2;
else
*max_ptr = max1;
}
}
How about find the max/min and the 2nd max/min value? Should implement in n + logn - 2
Use tournament method. We divide the data into n/2 groups, and we have one comparison in each group. That costs us n/2 comparisons so far. Clearly we keep halving the number of comparisons, and use n-1 searches to establish the "winner".

To find the second place, we need only look at all the data items "beaten" by the ultimate winner. There are logn "rounds", and so logn items in that group. This means we need another logn-1 comparisons to establish second place. The implementation looks like:

for (step =1; step < n/2; step *= 2)
for (i =0; i <n; i+= 2*step)
compare_and_swap(array[i], array[i+step]);

where 'compare_and_swap' compare two items and put the smaller to left and greater one to right.

Monday, April 21, 2008

perspective on performance

  • Algorithms and Data Structures
  • Algorithm Tuning
  • Data Structure Reorganization
  • Code Tuning
  • Hardware