diff --git a/server/aesdsocket.c b/server/aesdsocket.c index 1af4cd3..928eab3 100644 --- a/server/aesdsocket.c +++ b/server/aesdsocket.c @@ -17,7 +17,10 @@ * @references * 1. AESD Lectures and Slides * 2. https://beej.us/guide/bgnet/html/ - * + * 3. https://blog.taborkelly.net/programming/c/2016/01/09/sys-queue-example.html + * 4. https://linux.die.net/man/2/clock_gettime + * 5. https://man7.org/linux/man-pages/man2/clock_nanosleep.2.html + * 6. */ #define _POSIX_C_SOURCE 200112L // Enable POSIX features @@ -36,27 +39,48 @@ #include #include #include +#include "queue.h" +#include +#include +#include +#include +#include #define ERROR (-1) #define BACKLOG (10) #define PORT_NUM (9000) -#define BUF_SIZE (1024) +#define BUF_INITIAL_SIZE (1024) +#define TIMESTAMP_INTERVAL (10) -int sockfd, new_fd; +int sockfd; struct addrinfo *res; // will point to the results volatile sig_atomic_t caught_signal = 0; FILE *tmp_file = NULL; -char client_ip[INET_ADDRSTRLEN]; /* Size for IPv4 addresses */ -void cleanup() +/* The structure for the linked list that will manage server threads*/ +typedef struct server_thread_params { - if (new_fd != -1) - { - shutdown(new_fd, SHUT_RDWR); - close(new_fd); - syslog(LOG_DEBUG, "Closed connection from %s", client_ip); - } + pthread_t thread_id; + volatile bool thread_complete; + int client_fd; + char client_ip[INET_ADDRSTRLEN]; /* Size for IPv4 addresses */ + pthread_mutex_t *tmp_file_write_mutex; + FILE *tmp_file_server_thread; + SLIST_ENTRY(server_thread_params) link; +} server_thread_params_t; + +/* The structure for the timestamp thread*/ +typedef struct time_thread_params +{ + pthread_t thread_id; + pthread_mutex_t *tmp_file_write_mutex; + FILE *tmp_file_time_thread; +} time_thread_params_t; + +typedef SLIST_HEAD(socket_head,server_thread_params) head_t; +void cleanup() +{ if (sockfd != -1) { shutdown(sockfd, SHUT_RDWR); @@ -127,7 +151,6 @@ bool create_daemon () syslog(LOG_ERR, "Failed to redirect stdout"); } - if ((ret_stderr = dup2(file, STDERR_FILENO)) == ERROR) { syslog(LOG_ERR, "Failed to redirect stderr"); @@ -146,6 +169,187 @@ static void signal_handler (int signal_number) caught_signal = signal_number; } +void *threadfn_timestamp(void *time_thread_params_struct) +{ + time_thread_params_t *time_params = (time_thread_params_t*)time_thread_params_struct; + if (time_params == NULL) + { + syslog(LOG_ERR, "Time thread struct is NULL"); + return NULL; + } + + struct timespec wall_time; + char outstr[300]; + time_t t; + struct tm *tmp; + + /* Run until a signal caught */ + while(!caught_signal) + { + t = time(NULL); + tmp = localtime(&t); + if (tmp == NULL) + { + syslog(LOG_ERR, "Localtime"); + return NULL; + } + + if (clock_gettime(CLOCK_MONOTONIC, &wall_time) != 0) + { + syslog(LOG_ERR, "Failed clock_gettime"); + continue; + } + + wall_time.tv_sec += TIMESTAMP_INTERVAL; + + /* Sleep for 10 seconds */ + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wall_time, NULL); + + if (strftime(outstr, sizeof(outstr),"timestamp: %Y/%m/%d %H:%M:%S\n", tmp) == 0) + { + syslog(LOG_ERR, "strftime failed"); + continue; + } + + /* Lock mutex before writing to tmp file and set file position*/ + pthread_mutex_lock(time_params->tmp_file_write_mutex); + fseek(time_params->tmp_file_time_thread, 0, SEEK_END); + if ((fwrite(outstr, sizeof(char), strlen(outstr), time_params->tmp_file_time_thread)) < 0) + { + syslog(LOG_ERR, "Timestamp write failed"); + continue; + } + fflush(time_params->tmp_file_time_thread); + pthread_mutex_unlock(time_params->tmp_file_write_mutex); + } + + return NULL; +} + +int receive_data(server_thread_params_t *server_params, char **buf, size_t *receive_buf_size) +{ + int length; + size_t total_received = 0; + char *end_packet = NULL; + + do + { + if (total_received + 1 >= *receive_buf_size) + { + *receive_buf_size *= 2; + char *new_buf = realloc(*buf, *receive_buf_size); + if (new_buf == NULL) + { + syslog(LOG_ERR, "Realloc failed for receiving buffer"); + return -1; + } + memset(new_buf + total_received, 0, *receive_buf_size - total_received); + *buf = new_buf; + } + + length = recv(server_params->client_fd, *buf + total_received, *receive_buf_size - total_received - 1, 0); + if (length == -1) + { + syslog(LOG_ERR, "Receive failed"); + return -1; + } + + total_received += length; + end_packet = strchr(*buf, '\n'); + + } while (end_packet == NULL && length > 0); + + return (end_packet != NULL) ? 0 : -1; +} + +int process_data(server_thread_params_t *server_params, char *buf, size_t receive_buf_size) +{ + char *end_packet = strchr(buf, '\n'); + if (end_packet == NULL) + { + syslog(LOG_ERR, "Received without newline"); + return -1; + } + + size_t valid_size = end_packet - buf + 1; + buf[valid_size] = '\0'; + + pthread_mutex_lock(server_params->tmp_file_write_mutex); + fseek(server_params->tmp_file_server_thread, 0, SEEK_END); + size_t written_bytes = fwrite(buf, sizeof(char), valid_size, server_params->tmp_file_server_thread); + fflush(server_params->tmp_file_server_thread); + pthread_mutex_unlock(server_params->tmp_file_write_mutex); + + if (written_bytes < valid_size) + { + syslog(LOG_ERR, "Write to temp file failed"); + return -1; + } + + return 0; +} + +int send_response(server_thread_params_t *server_params, char *buf, size_t receive_buf_size) +{ + size_t read_bytes; + pthread_mutex_lock(server_params->tmp_file_write_mutex); + fseek(server_params->tmp_file_server_thread, 0, SEEK_SET); + while ((read_bytes = fread(buf, sizeof(char), receive_buf_size - 1, server_params->tmp_file_server_thread)) > 0) + { + syslog(LOG_INFO, "Read %s from file", buf); + fflush(server_params->tmp_file_server_thread); + if (send(server_params->client_fd, buf, read_bytes, 0) == -1) + { + syslog(LOG_ERR, "Send to client failed"); + pthread_mutex_unlock(server_params->tmp_file_write_mutex); + return -1; + } + } + pthread_mutex_unlock(server_params->tmp_file_write_mutex); + return 0; +} + +void *threadfn_server(void *server_thread_params_struct) +{ + server_thread_params_t *server_params = (server_thread_params_t*)server_thread_params_struct; + char *buf = NULL; + int result = 0; + + if (server_params == NULL) + { + syslog(LOG_ERR, "Thread server_thread_params is NULL"); + return NULL; + } + + do + { + size_t receive_buf_size = BUF_INITIAL_SIZE; + buf = malloc(receive_buf_size); + if (buf == NULL) + { + syslog(LOG_ERR, "Memory allocation failed for receiving buffer"); + result = -1; + break; + } + memset(buf, 0, receive_buf_size); + + result = receive_data(server_params, &buf, &receive_buf_size); + if (result != 0) break; + + result = process_data(server_params, buf, receive_buf_size); + if (result != 0) break; + + result = send_response(server_params, buf, receive_buf_size); + + } while (0); + + free(buf); + close(server_params->client_fd); + syslog(LOG_DEBUG, "Closed connection from %s", server_params->client_ip); + server_params->thread_complete = true; + return (void*)(intptr_t)result; +} + int main ( int argc, char **argv ) { openlog("socket", LOG_PID | LOG_CONS, LOG_USER); @@ -156,7 +360,7 @@ int main ( int argc, char **argv ) is_daemon = true; } - /* Lines 104 - 124 were referenced from https://beej.us/guide/bgnet/html/ */ + /* Lines 363 - 382 were referenced from https://beej.us/guide/bgnet/html/ */ int status; socklen_t addr_size; struct addrinfo hints; @@ -194,6 +398,7 @@ int main ( int argc, char **argv ) if (bind(sockfd, res->ai_addr, res->ai_addrlen) == -1) { syslog(LOG_ERR, "Bind failed"); + syslog(LOG_ERR, "bind failed: %s", strerror(errno)); cleanup(); exit(1); } @@ -216,14 +421,6 @@ int main ( int argc, char **argv ) exit(1); } - tmp_file = fopen("/var/tmp/aesdsocketdata", "w+"); - if (tmp_file == NULL) - { - syslog(LOG_ERR, "Failed to open /var/tmp/aesdsocketdata"); - cleanup(); - exit(1); - } - /* Setup signal handlers*/ struct sigaction new_action; memset(&new_action, 0, sizeof(struct sigaction)); @@ -239,9 +436,48 @@ int main ( int argc, char **argv ) syslog(LOG_ERR, "Sigaction for SIGINT failed"); } - /* Now accept an incoming connection in a loop while signal not caught*/ + pthread_mutex_t tmp_file_write_mutex; + /* Create a mutex for synchronising writes to tmp_file*/ + if(pthread_mutex_init(&tmp_file_write_mutex, NULL) != 0) + { + syslog(LOG_ERR, "Creating file write mutex failed"); + cleanup(); + exit(1); + } + + tmp_file = fopen("/var/tmp/aesdsocketdata", "w+"); + + time_thread_params_t *time_params = NULL; + time_params = (time_thread_params_t*)malloc(sizeof(time_thread_params_t)); + if(time_params == NULL) + { + syslog(LOG_ERR, "Malloc for time thread structure failed"); + cleanup(); + exit(1); + } + + time_params->tmp_file_write_mutex = &tmp_file_write_mutex; + time_params->tmp_file_time_thread = tmp_file; + + if ((pthread_create(&(time_params->thread_id), NULL, &threadfn_timestamp, (void*)time_params)) != 0) + { + syslog(LOG_ERR, "Timestamp thread creation failed"); + cleanup(); + exit(1); + } + + /* Initialize the head */ + head_t head; + SLIST_INIT(&head); + + /* Create the timestamp thread*/ + server_thread_params_t *server_params = NULL; + + /* Now accept incoming connections in a loop while signal not caught*/ while (!caught_signal) { + int new_fd; + char client_ip[INET_ADDRSTRLEN]; addr_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); if (new_fd == -1) @@ -249,113 +485,82 @@ int main ( int argc, char **argv ) syslog(LOG_ERR, "Accept failed: %s", strerror(errno)); continue; } - + inet_ntop(their_addr.ss_family, &(((struct sockaddr_in*)&their_addr)->sin_addr), client_ip, sizeof(client_ip)); syslog(LOG_DEBUG, "Accepted connection from %s", client_ip); - /* Dynamically allocate an initial buffer size, later resize as needed*/ - size_t receive_buf_size = BUF_SIZE; - char *buf = (char *)malloc(receive_buf_size); - memset(buf, 0, BUF_SIZE); - if (buf == NULL) + server_params = (server_thread_params_t*)malloc(sizeof(server_thread_params_t)); + if(server_params == NULL) { - syslog(LOG_ERR, "Memory allocation failed for receiving buffer"); - close(new_fd); - syslog(LOG_DEBUG, "Closed connection from %s", client_ip); + syslog(LOG_ERR, "Malloc for server thread params failed"); continue; } - int length; - size_t total_received = 0, valid_size = 0; - char *end_packet = NULL; - - /* Loop to receive data until a newline is found */ - do + server_params->thread_complete = false; + server_params->client_fd = new_fd; + strncpy(server_params->client_ip, client_ip, INET_ADDRSTRLEN); + server_params->tmp_file_write_mutex = &tmp_file_write_mutex; + server_params->tmp_file_server_thread = tmp_file; + + if ((pthread_create(&(server_params->thread_id), NULL, threadfn_server, (void*)server_params)) != 0) { - static int count = 0; - - /* Resize buffer dynamically if needed from the second count*/ - if ((total_received + 1 >= receive_buf_size) && (count != 0)) - { - /* Double the size */ - receive_buf_size *= 2; - char *new_buf = (char *)realloc(buf, receive_buf_size); - if (new_buf == NULL) - { - syslog(LOG_ERR, "Realloc failed for receiving buffer"); - free(buf); - close(new_fd); - syslog(LOG_DEBUG, "Closed connection from %s", client_ip); - continue; - } - memset(new_buf + total_received, 0, receive_buf_size - total_received); - buf = new_buf; - } + syslog(LOG_ERR, "Thread creation failed"); + free(server_params); + server_params = NULL; + continue; + } - /* Receive data. ssize_t recv(int sockfd, void buf[.len], size_t len, int flags);*/ - length = recv(new_fd, buf + total_received, receive_buf_size - total_received - 1, 0); - if (length == -1) - { - syslog(LOG_ERR, "Receive failed"); - free(buf); - close(new_fd); - syslog(LOG_DEBUG, "Closed connection from %s", client_ip); - continue; - } + /* Add the node to the SLIST*/ + SLIST_INSERT_HEAD(&head, server_params, link); - total_received += length; - end_packet = strchr(buf, '\n'); - count++; + /* Attempt to join threads by checking for the complete_thread flag*/ + server_thread_params_t *iterator = NULL; + server_thread_params_t *tmp = NULL; - } while ((end_packet == NULL) && (length > 0)); - - /* Check if we found a newline */ - if (end_packet != NULL) - { - /* Append to file only until \n */ - valid_size = end_packet - buf + 1; - /* Null terminate the string */ - buf[valid_size] = '\0'; + SLIST_FOREACH_SAFE(iterator, &head, link, tmp) + { + if (iterator->thread_complete == true) + { + if(pthread_join(iterator->thread_id, NULL) != 0) + { + syslog(LOG_ERR, "Thread join failed fir %ld", iterator->thread_id); + } + syslog(LOG_INFO, "Thread joined %ld", iterator->thread_id); - size_t written_bytes = fwrite(buf, sizeof(char), valid_size, tmp_file); - if(written_bytes < valid_size) - { - syslog(LOG_ERR, "Write to temp file failed"); - free(buf); - close(new_fd); - syslog(LOG_DEBUG, "Closed connection from %s", client_ip); - continue; + /* Remove node from the list and free the memory */ + SLIST_REMOVE(&head, iterator, server_thread_params, link); + free(iterator); + iterator = NULL; } - fflush(tmp_file); - } - else - { - syslog(LOG_ERR, "Received without newline\n"); } + } - /* Send back to client */ - fseek(tmp_file, 0, SEEK_SET); - - size_t read_bytes = 0; - do + /* Cleanup after caught signal */ + /* Mutex */ + pthread_mutex_destroy(&tmp_file_write_mutex); + /* Timestamp thread */ + pthread_cancel(time_params->thread_id); + pthread_join(time_params->thread_id, NULL); + free(time_params); + /* Server thread */ + server_thread_params_t *iterator = NULL; + server_thread_params_t *tmp = NULL; + SLIST_FOREACH_SAFE(iterator, &head, link, tmp) + { + if (iterator->thread_complete == true) { - /*Clear the buffer*/ - memset(buf, 0, receive_buf_size); - /* Read full contents of the file and send*/ - read_bytes = fread(buf, sizeof(char), receive_buf_size - 1, tmp_file); - fflush(tmp_file); - if (send(new_fd, buf, read_bytes, 0) == -1) + if(pthread_join(iterator->thread_id, NULL) != 0) { - syslog(LOG_ERR, "Send to client failed"); - break; + syslog(LOG_ERR, "Thread join failed fir %ld", iterator->thread_id); } - } while (read_bytes > 0); + syslog(LOG_INFO, "Thread joined %ld", iterator->thread_id); - free(buf); - close(new_fd); - syslog(LOG_DEBUG, "Closed connection from %s", client_ip); + /* Remove node from the list and free the memory */ + SLIST_REMOVE(&head, iterator, server_thread_params, link); + free(iterator); + iterator = NULL; + } } - cleanup(); closelog(); } \ No newline at end of file diff --git a/server/queue.h b/server/queue.h new file mode 100644 index 0000000..6d6b195 --- /dev/null +++ b/server/queue.h @@ -0,0 +1,787 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may be traversed in either direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _CLASS_HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_FROM + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT s s + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE s + s + + * _SWAP + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + unsigned long lastline; + unsigned long prevline; + const char *lastfile; + const char *prevfile; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define QMD_SAVELINK(name, link) +#define TRACEBUF +#define TRACEBUF_INITIALIZER +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +#define SLIST_CLASS_ENTRY(type) \ +struct { \ + class type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ + SLIST_INIT(head2); \ + } else if (SLIST_FIRST(head2) != NULL) { \ + while (SLIST_NEXT(curelm, field) != NULL) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + SLIST_INIT(head2); \ + } \ +} while (0) + +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +#define SLIST_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *stqh_first; /* first element */ \ + class type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +#define STAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, \ + QUEUE_TYPEOF(type), field.stqe_next)) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +#define LIST_CLASS_ENTRY(type) \ +struct { \ + class type *le_next; /* next element */ \ + class type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ + LIST_FIRST(head2)->field.le_prev = \ + &LIST_FIRST((head1)); \ + LIST_INIT(head2); \ + } \ + } else if (LIST_FIRST(head2) != NULL) { \ + while (LIST_NEXT(curelm, field) != NULL) \ + curelm = LIST_NEXT(curelm, field); \ + LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ + LIST_INIT(head2); \ + } \ +} while (0) + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, \ + QUEUE_TYPEOF(type), field.le_next)) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#endif /* !_SYS_QUEUE_H_ */ \ No newline at end of file diff --git a/server/valgrind-out.txt b/server/valgrind-out.txt index 392ee47..f345a54 100644 --- a/server/valgrind-out.txt +++ b/server/valgrind-out.txt @@ -1,129 +1,132 @@ -==4376== Memcheck, a memory error detector -==4376== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. -==4376== Using Valgrind-3.18.1-42b08ed5bd-20211015 and LibVEX; rerun with -h for copyright info -==4376== Command: ./aesdsocket -==4376== Parent PID: 4374 -==4376== ---4376-- ---4376-- Valgrind options: ---4376-- --error-exitcode=1 ---4376-- --leak-check=full ---4376-- --show-leak-kinds=all ---4376-- --track-origins=yes ---4376-- --errors-for-leak-kinds=definite ---4376-- --verbose ---4376-- --log-file=valgrind-out.txt ---4376-- Contents of /proc/version: ---4376-- Linux version 6.8.0-45-generic (buildd@lcy02-amd64-075) (x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #45~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Sep 11 15:25:05 UTC 2 ---4376-- ---4376-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3 ---4376-- Page sizes: currently 4096, max supported 4096 ---4376-- Valgrind library directory: /usr/libexec/valgrind ---4376-- Reading syms from /home/traptibalgi/assignment-1-traptibalgi/server/aesdsocket ---4376-- Reading syms from /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ---4376-- Considering /usr/lib/debug/.build-id/41/86944c50f8a32b47d74931e3f512b811813b64.debug .. ---4376-- .. build-id is valid ---4376-- Reading syms from /usr/libexec/valgrind/memcheck-amd64-linux ---4376-- object doesn't have a symbol table ---4376-- object doesn't have a dynamic symbol table ---4376-- Scheduler: using generic scheduler lock implementation. ---4376-- Reading suppressions file: /usr/libexec/valgrind/default.supp -==4376== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-4376-by-traptibalgi-on-??? -==4376== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-4376-by-traptibalgi-on-??? -==4376== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-4376-by-traptibalgi-on-??? -==4376== -==4376== TO CONTROL THIS PROCESS USING vgdb (which you probably -==4376== don't want to do, unless you know exactly what you're doing, -==4376== or are doing some strange experiment): -==4376== /usr/bin/vgdb --pid=4376 ...command... -==4376== -==4376== TO DEBUG THIS PROCESS USING GDB: start GDB like this -==4376== /path/to/gdb ./aesdsocket -==4376== and then give GDB the following command -==4376== target remote | /usr/bin/vgdb --pid=4376 -==4376== --pid is optional if only one valgrind process is running -==4376== ---4376-- REDIR: 0x402aa40 (ld-linux-x86-64.so.2:strlen) redirected to 0x580bcec2 (???) ---4376-- REDIR: 0x402a810 (ld-linux-x86-64.so.2:index) redirected to 0x580bcedc (???) ---4376-- Reading syms from /usr/libexec/valgrind/vgpreload_core-amd64-linux.so ---4376-- object doesn't have a symbol table ---4376-- Reading syms from /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so ---4376-- object doesn't have a symbol table -==4376== WARNING: new redirection conflicts with existing -- ignoring it ---4376-- old: 0x0402aa40 (strlen ) R-> (0000.0) 0x580bcec2 ??? ---4376-- new: 0x0402aa40 (strlen ) R-> (2007.0) 0x0484ee30 strlen ---4376-- REDIR: 0x4027220 (ld-linux-x86-64.so.2:strcmp) redirected to 0x484fcd0 (strcmp) ---4376-- REDIR: 0x402afa0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4853840 (mempcpy) ---4376-- Reading syms from /usr/lib/x86_64-linux-gnu/libc.so.6 ---4376-- Considering /usr/lib/debug/.build-id/49/0fef8403240c91833978d494d39e537409b92e.debug .. ---4376-- .. build-id is valid -==4376== WARNING: new redirection conflicts with existing -- ignoring it ---4376-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign ---4376-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e050 aligned_alloc -==4376== WARNING: new redirection conflicts with existing -- ignoring it ---4376-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign ---4376-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e020 aligned_alloc -==4376== WARNING: new redirection conflicts with existing -- ignoring it ---4376-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign ---4376-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e050 aligned_alloc -==4376== WARNING: new redirection conflicts with existing -- ignoring it ---4376-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign ---4376-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e020 aligned_alloc ---4376-- REDIR: 0x4913720 (libc.so.6:strnlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49139e0 (libc.so.6:strpbrk) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49132e0 (libc.so.6:strcmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4931cd0 (libc.so.6:wcsnlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49146d0 (libc.so.6:memset) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4930540 (libc.so.6:wcslen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4914c10 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4930370 (libc.so.6:wcschr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4913260 (libc.so.6:index) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4913960 (libc.so.6:rindex) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49145a0 (libc.so.6:memmove) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49303f0 (libc.so.6:wcscmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49149e0 (libc.so.6:stpncpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49309b0 (libc.so.6:wmemchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4913830 (libc.so.6:strncmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4914a70 (libc.so.6:strcasecmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4913420 (libc.so.6:strcspn) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4930470 (libc.so.6:wcscpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49131d0 (libc.so.6:strcat) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4914b60 (libc.so.6:strncasecmp_l) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4914480 (libc.so.6:bcmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x491c570 (libc.so.6:memrchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4916010 (libc.so.6:strchrnul) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4913390 (libc.so.6:strcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4914b10 (libc.so.6:strcasecmp_l) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49136a0 (libc.so.6:strlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49138d0 (libc.so.6:strncpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4914950 (libc.so.6:stpcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49143f0 (libc.so.6:memchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4913b00 (libc.so.6:strspn) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x49147d0 (libc.so.6:mempcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4914ac0 (libc.so.6:strncasecmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4915f80 (libc.so.6:rawmemchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) ---4376-- REDIR: 0x4925650 (libc.so.6:__strrchr_sse2) redirected to 0x484e870 (__strrchr_sse2) ---4376-- REDIR: 0x492ff60 (libc.so.6:__memset_sse2_unaligned) redirected to 0x4852770 (memset) ---4376-- REDIR: 0x49100a0 (libc.so.6:malloc) redirected to 0x4848820 (malloc) ---4376-- REDIR: 0x49103e0 (libc.so.6:free) redirected to 0x484b210 (free) ---4376-- REDIR: 0x4913fc0 (libc.so.6:__GI_strstr) redirected to 0x4853ae0 (__strstr_sse2) ---4376-- REDIR: 0x4925440 (libc.so.6:__strchrnul_sse2) redirected to 0x4853330 (strchrnul) ---4376-- REDIR: 0x492a890 (libc.so.6:__strcpy_sse2_unaligned) redirected to 0x484ee60 (strcpy) ---4376-- REDIR: 0x4911520 (libc.so.6:calloc) redirected to 0x484d9d0 (calloc) ---4376-- REDIR: 0x4925950 (libc.so.6:__strlen_sse2) redirected to 0x484ed70 (__strlen_sse2) ---4376-- REDIR: 0x492f870 (libc.so.6:memcpy@GLIBC_2.2.5) redirected to 0x484fe00 (memcpy@GLIBC_2.2.5) ---4376-- REDIR: 0x4a0db30 (libc.so.6:__memcmp_sse4_1) redirected to 0x4851f80 (__memcmp_sse4_1) ---4376-- REDIR: 0x491dd70 (libc.so.6:__strcmp_sse2_unaligned) redirected to 0x484fbd0 (strcmp) ---4376-- REDIR: 0x492f850 (libc.so.6:__mempcpy_sse2_unaligned) redirected to 0x4853440 (mempcpy) ---4376-- REDIR: 0x4910740 (libc.so.6:realloc) redirected to 0x484dc50 (realloc) ---4376-- REDIR: 0x4925210 (libc.so.6:__strchr_sse2) redirected to 0x484e990 (__strchr_sse2) ---4376-- REDIR: 0x491f880 (libc.so.6:__memchr_sse2) redirected to 0x484fd50 (memchr) ---4376-- REDIR: 0x492bed0 (libc.so.6:__stpcpy_sse2_unaligned) redirected to 0x4852370 (__stpcpy_sse2_unaligned) -==4376== -==4376== HEAP SUMMARY: -==4376== in use at exit: 0 bytes in 0 blocks -==4376== total heap usage: 60 allocs, 60 frees, 195,884 bytes allocated -==4376== -==4376== All heap blocks were freed -- no leaks are possible -==4376== -==4376== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) +==101127== Memcheck, a memory error detector +==101127== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. +==101127== Using Valgrind-3.18.1-42b08ed5bd-20211015 and LibVEX; rerun with -h for copyright info +==101127== Command: ./aesdsocket +==101127== Parent PID: 101125 +==101127== +--101127-- +--101127-- Valgrind options: +--101127-- --error-exitcode=1 +--101127-- --leak-check=full +--101127-- --show-leak-kinds=all +--101127-- --track-origins=yes +--101127-- --errors-for-leak-kinds=definite +--101127-- --verbose +--101127-- --log-file=valgrind-out.txt +--101127-- Contents of /proc/version: +--101127-- Linux version 6.8.0-45-generic (buildd@lcy02-amd64-075) (x86_64-linux-gnu-gcc-12 (Ubuntu 12.3.0-1ubuntu1~22.04) 12.3.0, GNU ld (GNU Binutils for Ubuntu) 2.38) #45~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Sep 11 15:25:05 UTC 2 +--101127-- +--101127-- Arch and hwcaps: AMD64, LittleEndian, amd64-cx16-lzcnt-rdtscp-sse3-ssse3 +--101127-- Page sizes: currently 4096, max supported 4096 +--101127-- Valgrind library directory: /usr/libexec/valgrind +--101127-- Reading syms from /home/traptibalgi/assignment-1-traptibalgi/server/aesdsocket +--101127-- Reading syms from /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 +--101127-- Considering /usr/lib/debug/.build-id/41/86944c50f8a32b47d74931e3f512b811813b64.debug .. +--101127-- .. build-id is valid +--101127-- Reading syms from /usr/libexec/valgrind/memcheck-amd64-linux +--101127-- object doesn't have a symbol table +--101127-- object doesn't have a dynamic symbol table +--101127-- Scheduler: using generic scheduler lock implementation. +--101127-- Reading suppressions file: /usr/libexec/valgrind/default.supp +==101127== embedded gdbserver: reading from /tmp/vgdb-pipe-from-vgdb-to-101127-by-traptibalgi-on-??? +==101127== embedded gdbserver: writing to /tmp/vgdb-pipe-to-vgdb-from-101127-by-traptibalgi-on-??? +==101127== embedded gdbserver: shared mem /tmp/vgdb-pipe-shared-mem-vgdb-101127-by-traptibalgi-on-??? +==101127== +==101127== TO CONTROL THIS PROCESS USING vgdb (which you probably +==101127== don't want to do, unless you know exactly what you're doing, +==101127== or are doing some strange experiment): +==101127== /usr/bin/vgdb --pid=101127 ...command... +==101127== +==101127== TO DEBUG THIS PROCESS USING GDB: start GDB like this +==101127== /path/to/gdb ./aesdsocket +==101127== and then give GDB the following command +==101127== target remote | /usr/bin/vgdb --pid=101127 +==101127== --pid is optional if only one valgrind process is running +==101127== +--101127-- REDIR: 0x402aa40 (ld-linux-x86-64.so.2:strlen) redirected to 0x580bcec2 (???) +--101127-- REDIR: 0x402a810 (ld-linux-x86-64.so.2:index) redirected to 0x580bcedc (???) +--101127-- Reading syms from /usr/libexec/valgrind/vgpreload_core-amd64-linux.so +--101127-- object doesn't have a symbol table +--101127-- Reading syms from /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so +--101127-- object doesn't have a symbol table +==101127== WARNING: new redirection conflicts with existing -- ignoring it +--101127-- old: 0x0402aa40 (strlen ) R-> (0000.0) 0x580bcec2 ??? +--101127-- new: 0x0402aa40 (strlen ) R-> (2007.0) 0x0484ee30 strlen +--101127-- REDIR: 0x4027220 (ld-linux-x86-64.so.2:strcmp) redirected to 0x484fcd0 (strcmp) +--101127-- REDIR: 0x402afa0 (ld-linux-x86-64.so.2:mempcpy) redirected to 0x4853840 (mempcpy) +--101127-- Reading syms from /usr/lib/x86_64-linux-gnu/libc.so.6 +--101127-- Considering /usr/lib/debug/.build-id/49/0fef8403240c91833978d494d39e537409b92e.debug .. +--101127-- .. build-id is valid +==101127== WARNING: new redirection conflicts with existing -- ignoring it +--101127-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign +--101127-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e050 aligned_alloc +==101127== WARNING: new redirection conflicts with existing -- ignoring it +--101127-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign +--101127-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e020 aligned_alloc +==101127== WARNING: new redirection conflicts with existing -- ignoring it +--101127-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign +--101127-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e050 aligned_alloc +==101127== WARNING: new redirection conflicts with existing -- ignoring it +--101127-- old: 0x04910c60 (memalign ) R-> (1011.0) 0x0484e080 memalign +--101127-- new: 0x04910c60 (memalign ) R-> (1017.0) 0x0484e020 aligned_alloc +--101127-- REDIR: 0x4913720 (libc.so.6:strnlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49139e0 (libc.so.6:strpbrk) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49132e0 (libc.so.6:strcmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4931cd0 (libc.so.6:wcsnlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49146d0 (libc.so.6:memset) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4930540 (libc.so.6:wcslen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4914c10 (libc.so.6:memcpy@@GLIBC_2.14) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4930370 (libc.so.6:wcschr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4913260 (libc.so.6:index) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4913960 (libc.so.6:rindex) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49145a0 (libc.so.6:memmove) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49303f0 (libc.so.6:wcscmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49149e0 (libc.so.6:stpncpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49309b0 (libc.so.6:wmemchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4913830 (libc.so.6:strncmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4914a70 (libc.so.6:strcasecmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4913420 (libc.so.6:strcspn) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4930470 (libc.so.6:wcscpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49131d0 (libc.so.6:strcat) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4914b60 (libc.so.6:strncasecmp_l) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4914480 (libc.so.6:bcmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x491c570 (libc.so.6:memrchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4916010 (libc.so.6:strchrnul) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4913390 (libc.so.6:strcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4914b10 (libc.so.6:strcasecmp_l) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49136a0 (libc.so.6:strlen) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49138d0 (libc.so.6:strncpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4914950 (libc.so.6:stpcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49143f0 (libc.so.6:memchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4913b00 (libc.so.6:strspn) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x49147d0 (libc.so.6:mempcpy) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4914ac0 (libc.so.6:strncasecmp) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4915f80 (libc.so.6:rawmemchr) redirected to 0x483f220 (_vgnU_ifunc_wrapper) +--101127-- REDIR: 0x4925650 (libc.so.6:__strrchr_sse2) redirected to 0x484e870 (__strrchr_sse2) +--101127-- REDIR: 0x492ff60 (libc.so.6:__memset_sse2_unaligned) redirected to 0x4852770 (memset) +--101127-- REDIR: 0x49100a0 (libc.so.6:malloc) redirected to 0x4848820 (malloc) +--101127-- REDIR: 0x49103e0 (libc.so.6:free) redirected to 0x484b210 (free) +--101127-- REDIR: 0x4913fc0 (libc.so.6:__GI_strstr) redirected to 0x4853ae0 (__strstr_sse2) +--101127-- REDIR: 0x4911520 (libc.so.6:calloc) redirected to 0x484d9d0 (calloc) +--101127-- REDIR: 0x4925950 (libc.so.6:__strlen_sse2) redirected to 0x484ed70 (__strlen_sse2) +--101127-- REDIR: 0x492f870 (libc.so.6:memcpy@GLIBC_2.2.5) redirected to 0x484fe00 (memcpy@GLIBC_2.2.5) +--101127-- REDIR: 0x4a0db30 (libc.so.6:__memcmp_sse4_1) redirected to 0x4851f80 (__memcmp_sse4_1) +--101127-- REDIR: 0x491dd70 (libc.so.6:__strcmp_sse2_unaligned) redirected to 0x484fbd0 (strcmp) +--101127-- REDIR: 0x4925440 (libc.so.6:__strchrnul_sse2) redirected to 0x4853330 (strchrnul) +--101127-- REDIR: 0x492a890 (libc.so.6:__strcpy_sse2_unaligned) redirected to 0x484ee60 (strcpy) +--101127-- REDIR: 0x492f850 (libc.so.6:__mempcpy_sse2_unaligned) redirected to 0x4853440 (mempcpy) +--101127-- REDIR: 0x4910740 (libc.so.6:realloc) redirected to 0x484dc50 (realloc) +--101127-- REDIR: 0x492aec0 (libc.so.6:__strncpy_sse2_unaligned) redirected to 0x484f2e0 (__strncpy_sse2_unaligned) +--101127-- REDIR: 0x4925210 (libc.so.6:__strchr_sse2) redirected to 0x484e990 (__strchr_sse2) +--101127-- REDIR: 0x492bed0 (libc.so.6:__stpcpy_sse2_unaligned) redirected to 0x4852370 (__stpcpy_sse2_unaligned) +--101127-- Reading syms from /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 +--101127-- object doesn't have a symbol table +--101127-- Discarding syms at 0x6e9e660-0x6eb4805 in /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 (have_dinfo 1) +==101127== +==101127== HEAP SUMMARY: +==101127== in use at exit: 0 bytes in 0 blocks +==101127== total heap usage: 267 allocs, 267 frees, 645,636 bytes allocated +==101127== +==101127== All heap blocks were freed -- no leaks are possible +==101127== +==101127== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)