Friday, April 27, 2012

Simple Memory Pool in C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>


#define MEMORY_POOL_ALLOCED_CONST   ((void *) 0xFFFFFFFFu)

typedef struct memory_pool_s
{
  void *pool;
  void *empty_blocks;
  size_t block_size;
  size_t count;
} __attribute__ ((__aligned__)) memory_pool_t;

memory_pool_t * memory_pool_create(size_t bs, size_t c);
void memory_pool_destroy(memory_pool_t *mp);
void memory_pool_clear(memory_pool_t *mp);
void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value));
void * memory_pool_alloc(memory_pool_t *mp);
void memory_pool_free(memory_pool_t *mp, void *p);


memory_pool_t * memory_pool_create(size_t bs, size_t c)
{
  memory_pool_t *mp = malloc(sizeof(memory_pool_t));
  if (!mp)
    return NULL;

  mp->block_size = bs;
  mp->count = c;

  mp->pool = malloc((mp->block_size + sizeof(void *)) * mp->count);

  memory_pool_clear(mp);

  mp->empty_blocks = mp->pool;

  return mp;
}

void memory_pool_destroy(memory_pool_t *mp)
{
  if (!mp)
    return;

  memory_pool_clear(mp);
  free(mp->pool);
  free(mp);
}


void memory_pool_clear(memory_pool_t *mp)
{
  if (!mp)
    return;

  size_t i;
  void **p;

  for (i = 0; i < mp->count - 1; i++)
  {
    p = (void **) ((uint8_t *) mp->pool + (mp->block_size * (i + 1) +
                   sizeof(void *) * i));
    *p = (uint8_t *) mp->pool + (mp->block_size + sizeof(void *)) * (i + 1);
  }

  p = (void **) ((uint8_t *) mp->pool + (mp->block_size * mp->count +
                 sizeof(void *) * (mp->count - 1)));
  *p = NULL;

  mp->empty_blocks = mp->pool;
}

void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value))
{
  printf("start: %p, size: %d, count: %d\n", mp->pool,
         (mp->block_size + sizeof(void *)) * mp->count, mp->count);

  void *block;
  void **next;
  size_t i;

  for (i = 0; i < mp->count; i++)
  {
    block = (void *) ((uint8_t *) mp->pool + (mp->block_size * i) +
                      sizeof(void *) * i);
    next = (void **) ((uint8_t *) block + sizeof(void *));

    printf("block #%i(%p):", i, block);

    if (*next == MEMORY_POOL_ALLOCED_CONST)
    {
      printf(" allocated");

      if (print_func)
      {
        printf(", value: ");
        print_func(block);
      }

      printf("\n");
    } else
    {
      printf(" free, next address %p\n", *next);
    }
  }
}

void * memory_pool_alloc(memory_pool_t *mp)
{
  void *p;

  if (mp->empty_blocks)
  {
    p = mp->empty_blocks;
    mp->empty_blocks = * (void **) ((uint8_t *) mp->empty_blocks +
                                    mp->block_size);
    *(void **) ((uint8_t *) p + mp->block_size) = MEMORY_POOL_ALLOCED_CONST;
    return p;
  } else
  {
    return NULL;
  }
}

void memory_pool_free(memory_pool_t *mp, void *p)
{
  if (p && (p >= mp->pool) && (p <= (void *) ((uint8_t *) mp->pool +
      (mp->block_size + sizeof(void *)) * mp->count)))
  {
    *(void **) ((uint8_t *) p + mp->block_size) = mp->empty_blocks;
    mp->empty_blocks = p;
  }
}


void print_intptr(void *p)
{
  printf("%d", *(int *) p);
}

int main(int argc, char *argv[])
{
  int *value;
  int c = 0;

  memory_pool_t *mp = memory_pool_create(sizeof(int), 128);

  memory_pool_dump(mp, print_intptr);

  while ((value = memory_pool_alloc(mp)))
  {
    *value = c++;
  }

  memory_pool_dump(mp, print_intptr);

  memory_pool_destroy(mp);

  return EXIT_SUCCESS;
}

Wednesday, November 9, 2011

Sine function using inline assembly

static inline float sin(float angle)
{
  float answer;
  asm ("fsin" : "=t" (answer) : "0" (angle));
  return answer;
}

Friday, May 27, 2011

Saving debug symbols to separate file


objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"


--
source: stackoverflow

Thursday, November 25, 2010

Linux sockets example


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>


#define EPOLL_ARRAY_SIZE   64


void sprint_buffer(const char *buffer, int size)
{
   
int i;
   
for (i = 0; i < size; i++)
   
{
     
if (isprint(buffer[i]))
         printf
("%c", buffer[i]);
     
else
         printf
("\\0x%02X", buffer[i]);
   
}
}

int main(int argc, char *argv[])
{
   
int sd, efd, clientsd, fd;
   
struct sockaddr_in bindaddr, peeraddr;
   socklen_t salen
= sizeof(peeraddr);
   
int pollsize = 1;
   
struct epoll_event ev;
   
struct epoll_event epoll_events[EPOLL_ARRAY_SIZE];
   uint32_t events
;
   
unsigned short port = 20000;
   
int i, rval, on = 1;
   ssize_t rc
;
   
char buffer[1024];


   efd
= epoll_create(pollsize);

   
if (efd < 0)
   
{
      printf
("Could not create the epoll fd: %m");
     
return 1;
   
}

   sd
= socket(AF_INET, SOCK_STREAM, 0);
   
if (sd < 0)
   
{
      printf
("Could not create new socket: %m\n");
     
return 2;
   
}

   printf
("New socket created with sd %d\n", sd);

   
if (fcntl(sd, F_SETFL, O_NONBLOCK))
   
{
      printf
("Could not make the socket non-blocking: %m\n");
      close
(sd);
     
return 3;
   
}

   
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
   
{
      printf
("Could not set socket %d option for reusability: %m\n", sd);
      close
(sd);
     
return 4;
   
}

   bindaddr
.sin_addr.s_addr = htonl(INADDR_ANY);
   bindaddr
.sin_family= AF_INET;
   bindaddr
.sin_port = htons(port);

   
if (bind(sd, (struct sockaddr *) &bindaddr, sizeof(struct sockaddr_in)) < 0)
   
{
      printf
("Could not bind socket %d to address 'INADDR_ANY' and port %u: %m", sd, port);
      close
(sd);
     
return 5;
   
}
   
else
   
{
      printf
("Bound socket %d to address 'INADDR_ANY' and port %u\n", sd, port);
   
}

   
if (listen(sd, SOMAXCONN))
   
{
      printf
("Could not start listening on server socket %d: %m\n", sd);
     
goto cleanup;
   
}
   
else
   
{
      printf
("Server socket %d started listening to address 'INADDR_ANY' and port %u\n", sd, port);
   
}

   ev
.events = EPOLLIN;
   ev
.data.u64 = 0LL;
   ev
.data.fd = sd;

   
if (epoll_ctl(efd, EPOLL_CTL_ADD, sd, &ev) < 0)
   
{
      printf
("Couldn't add server socket %d to epoll set: %m\n", sd);
     
goto cleanup;      
   
}

   
for (;;)
   
{
      printf
("Starting epoll_wait on %d fds\n", pollsize);

     
while ((rval = epoll_wait(efd, epoll_events, EPOLL_ARRAY_SIZE, -1)) < 0)
     
{
         
if ((rval < 0) && (errno != EINTR))
         
{
            printf
("EPoll on %d fds failed: %m\n", pollsize);
           
goto cleanup;
         
}
     
}

     
for (i = 0; i < rval; i++)
     
{
         events
= epoll_events[i].events;
         fd
= epoll_events[i].data.fd;

         
if (events & EPOLLERR)
         
{
           
if (fd == sd)
           
{
               printf
("EPoll on %d fds failed: %m\n", pollsize);
               
goto cleanup;
           
} else
           
{
               printf
("Closing socket with sd %d\n", fd);
               shutdown
(fd, SHUT_RDWR);
               close
(fd);
               
continue;
           
}
         
}

         
if (events & EPOLLHUP)
         
{
           
if (fd == sd)
           
{
               printf
("EPoll on %d fds failed: %m\n", pollsize);
               
goto cleanup;
           
} else
           
{
               printf
("Closing socket with sd %d\n", fd);
               shutdown
(fd, SHUT_RDWR);
               close
(fd);
               
continue;
           
}
         
}

         
if (events & EPOLLRDHUP)
         
{
           
if (fd == sd)
           
{
               printf
("EPoll on %d fds failed: %m\n", pollsize);
               
goto cleanup;
           
} else
           
{
               printf
("Closing socket with sd %d\n", fd);
               shutdown
(fd, SHUT_RDWR);
               close
(fd);
               
continue;
           
}
         
}

         
if (events & EPOLLOUT)
         
{
           
if (fd != sd)
           
{
               rc
= snprintf(buffer, sizeof(buffer), "Hello socket %d from server socket %d!\n", fd, sd);
               
while ((rc = send(fd, buffer, rc, 0)) < 0)
               
{
                 
if ((fd < 0) && (errno != EINTR))
                 
{
                     printf
("Send to socket %d failed: %m\n", fd);
                     pollsize
--;
                     shutdown
(fd, SHUT_RDWR);
                     close
(fd);
                     
continue;
                 
}
               
}

               
if (rc == 0)
               
{
                  printf
("Closing socket with sd %d\n", fd);
                  pollsize
--;
                  shutdown
(fd, SHUT_RDWR);
                  close
(fd);
                 
continue;
               
} else if (rc > 0)
               
{
                  printf
("Sent '");
                  sprint_buffer
(buffer, rc);
                  printf
("' to socket with sd %d\n", fd);

                  ev
.events = EPOLLIN;
                  ev
.data.u64 = 0LL;
                  ev
.data.fd = fd;

                 
if (epoll_ctl(efd, EPOLL_CTL_MOD, fd, &ev) < 0)
                 
{
                     printf
("Couldn't modify client socket %d in epoll set: %m\n", fd);
                     
goto cleanup;      
                 
}
               
}
           
}
         
}

         
if (events & EPOLLIN)
         
{
           
if (fd == sd)
           
{
               
while ((clientsd = accept(sd, (struct sockaddr *) &peeraddr, &salen)) < 0)
               
{
                 
if ((clientsd < 0) && (errno != EINTR))
                 
{
                     printf
("Accept on socket %d failed: %m\n", sd);
                     
goto cleanup;
                 
}
               
}

               
if (inet_ntop(AF_INET, &peeraddr.sin_addr.s_addr, buffer, sizeof(buffer)) != NULL)
               
{
                  printf
("Accepted connection from %s:%u, assigned new sd %d\n", buffer, ntohs(peeraddr.sin_port), clientsd);
               
} else
               
{
                  printf
("Failed to convert address from binary to text form: %m\n");
               
}

               ev
.events = EPOLLIN;
               ev
.data.u64 = 0LL;
               ev
.data.fd = clientsd;    

               
if (epoll_ctl(efd, EPOLL_CTL_ADD, clientsd, &ev) < 0)
               
{
                  printf
("Couldn't add client socket %d to epoll set: %m\n", clientsd);
                 
goto cleanup;      
               
}

               pollsize
++;
           
} else
           
{
               
while ((rc = recv(fd, buffer, sizeof(buffer), 0)) < 0)
               
{
                 
if ((fd < 0) && (errno != EINTR))
                 
{
                     printf
("Receive from socket %d failed: %m\n", fd);
                     pollsize
--;
                     shutdown
(fd, SHUT_RDWR);
                     close
(fd);
                     
continue;
                 
}
               
}

               
if (rc == 0)
               
{
                  printf
("Closing socket with sd %d\n", fd);
                  pollsize
--;
                  shutdown
(fd, SHUT_RDWR);
                  close
(fd);
                 
continue;
               
} else if (rc > 0)
               
{
                  printf
("Received '");
                  sprint_buffer
(buffer, rc);
                  printf
("' from socket with sd %d\n", fd);

                  ev
.events = EPOLLIN | EPOLLOUT;
                  ev
.data.u64 = 0LL;
                  ev
.data.fd = fd;

                 
if (epoll_ctl(efd, EPOLL_CTL_MOD, fd, &ev) < 0)
                 
{
                     printf
("Couldn't modify client socket %d in epoll set: %m\n", fd);
                     
goto cleanup;      
                 
}
               
}
           
}
         
}
     
}
   
}

cleanup
:
   shutdown
(sd, SHUT_RDWR);
   close
(sd);

   
return 0;
}