INCDIR := .
SRCDIR := .
-SRCS := main.c
+SRCS := main.c \
+ libft_extract.c \
+ init.c \
+ philos.c \
+ check_death.c \
+ parsing.c \
+ time.c \
+ print.c \
SRCS := $(addprefix $(SRCDIR)/, $(SRCS))
OBJS := $(SRCS:%.c=%.o)
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* check_death.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/03/19 15:53:52 by ljiriste #+# #+# */
+/* Updated: 2024/03/21 10:49:08 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <stddef.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int philo_died(t_philo *philo, t_settings *set)
+{
+ size_t i;
+ suseconds_t now;
+
+ i = 0;
+ now = cur_time_sus();
+ while (i < set->philo_count)
+ {
+ if ((now - philo->last_eaten) > set->time_to_die)
+ {
+ pthread_mutex_lock(&set->terminal);
+ printf("%li %lu %s\n", (cur_time_sus() - set->program_start)
+ / 1000, i + 1, G_DIE_STR);
+ set->end = 1;
+ pthread_mutex_unlock(&set->terminal);
+ return (1);
+ }
+ ++i;
+ }
+ return (0);
+}
+
+static int all_full(t_philo *philos, t_settings *set)
+{
+ size_t i;
+
+ i = 0;
+ while (i < set->philo_count)
+ {
+ if (philos[i].times_eaten < set->min_eats_num)
+ return (0);
+ ++i;
+ }
+ return (1);
+}
+
+static suseconds_t time_to_starve(t_philo *philos, t_settings *set)
+{
+ suseconds_t furthest_eaten;
+ size_t i;
+
+ i = 0;
+ while (i < set->philo_count)
+ {
+ if (furthest_eaten > philos[i].last_eaten)
+ furthest_eaten = philos[i].last_eaten;
+ ++i;
+ }
+ return (set->time_to_die - (cur_time_sus() - furthest_eaten));
+}
+
+void check_death(t_philo *philos, t_settings *set)
+{
+ while (!philo_died(philos, set))
+ {
+ if (all_full(philos, set))
+ {
+ pthread_mutex_lock(&set->terminal);
+ printf("%li %s\n", (cur_time_sus() - set->program_start) / 1000,
+ G_FED_STR);
+ set->end = 1;
+ pthread_mutex_unlock(&set->terminal);
+ return ;
+ }
+ usleep(time_to_starve(philos, set));
+ }
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* init.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/03/19 15:48:58 by ljiriste #+# #+# */
+/* Updated: 2024/03/21 10:04:35 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <pthread.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+int init_settings(int argc, char **argv, t_settings *set)
+{
+ pthread_mutex_init(&set->terminal, NULL);
+ set->end = 0;
+ return (parse_input(argc, argv, set));
+}
+
+pthread_mutex_t *init_forks(size_t count)
+{
+ pthread_mutex_t *forks;
+
+ forks = malloc(sizeof(pthread_mutex_t) * count);
+ if (!forks)
+ return (NULL);
+ while (count > 0)
+ {
+ pthread_mutex_init(&forks[--count], NULL);
+ }
+ return (forks);
+}
+
+t_philo *build_philos(pthread_mutex_t *forks, t_settings *set)
+{
+ t_philo *philos;
+ size_t count;
+
+ if (!forks)
+ return (NULL);
+ count = set->philo_count;
+ philos = malloc(sizeof(t_philo) * count);
+ if (!philos)
+ return (NULL);
+ philos[0].forks[1] = forks + count - 1;
+ while (count > 0)
+ {
+ --count;
+ philos[count].id = count + 1;
+ philos[count].times_eaten = 0;
+ philos[count].settings = set;
+ philos[count].forks[0] = forks + count - count % 2;
+ if (count > 0)
+ philos[count].forks[1] = forks + count - (count + 1) % 2;
+ }
+ return (philos);
+}
+
+void create_philos(t_philo *philos, pthread_t *threads, t_settings *set)
+{
+ size_t count;
+
+ count = set->philo_count;
+ while (count > 0)
+ {
+ --count;
+ philos[count].last_eaten = set->program_start;
+ pthread_create(threads + count, NULL, be_a_philosopher, philos + count);
+ }
+ return ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* libft_extract.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/03/19 15:45:40 by ljiriste #+# #+# */
+/* Updated: 2024/03/19 15:48:03 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+size_t ft_atos(const char *str)
+{
+ size_t res;
+
+ res = 0;
+ while (*str == ' ')
+ ++str;
+ if (*str == '+')
+ ++str;
+ while ('0' <= *str && *str <= '9')
+ {
+ res *= 10;
+ res += *str - '0';
+ ++str;
+ }
+ return (res);
+}
+
+static size_t size_needed(int n)
+{
+ size_t res;
+
+ res = 1;
+ if (n == 0)
+ return (2);
+ if (n < 0)
+ ++res;
+ while (n != 0)
+ {
+ ++res;
+ n /= 10;
+ }
+ return (res);
+}
+
+char *ft_stoa(int n)
+{
+ size_t size;
+ char *res;
+
+ size = size_needed(n);
+ res = malloc(size * sizeof(char));
+ if (res == NULL)
+ return (res);
+ res[--size] = '\0';
+ if (n == 0 && res)
+ res[0] = '0';
+ else if (n < 0 && res)
+ {
+ res[0] = '-';
+ res[--size] = '0' - (n % 10);
+ n = -(n / 10);
+ }
+ while (n > 0 && res)
+ {
+ res[--size] = '0' + (n % 10);
+ n /= 10;
+ }
+ return (res);
+}
+
+int ft_strcmp(const char *s1, const char *s2)
+{
+ size_t i;
+
+ i = 0;
+ while (s1[i] == s2[i] && s1[i] && s2[i])
+ ++i;
+ return ((unsigned char)s1[i] - (unsigned char)s2[i]);
+}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/05 12:49:40 by ljiriste #+# #+# */
-/* Updated: 2024/03/19 15:39:58 by ljiriste ### ########.fr */
+/* Updated: 2024/03/21 10:26:01 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include <unistd.h>
-static const char *g_fed_str = "All philosophers are well fed";
-static const char *g_think_str = "is thinking";
-static const char *g_fork_str = "has taken a fork";
-static const char *g_eat_str = "is eating";
-static const char *g_sleep_str = "is sleeping";
-static const char *g_die_str = "died";
-// unsigned long would be more apropriate for min_eats_num
-// but for the ease of parsing I'm using size_t
-
-suseconds_t cur_time_sus(void)
-{
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- return (tv.tv_sec * 1000000 + tv.tv_usec);
-}
-
-void thread_print(t_settings *set, size_t id, const char *message)
-{
- pthread_mutex_lock(&set->terminal);
- if (set->end)
- {
- pthread_mutex_unlock(&set->terminal);
- return ;
- }
- printf("%li %li %s\n", (cur_time_sus() - set->program_start) / 1000,
- id, message);
- pthread_mutex_unlock(&set->terminal);
- return ;
-}
-
-void philo_sleep(t_settings *set, size_t id)
-{
- thread_print(set, id, g_sleep_str);
- usleep(set->time_to_sleep);
- return ;
-}
-
-void philo_think(t_settings *set, size_t id)
-{
- thread_print(set, id, g_think_str);
- return ;
-}
-
-void philo_eat(t_philo *philo)
-{
- pthread_mutex_lock(philo->forks[0]);
- thread_print(philo->settings, philo->id, g_fork_str);
- pthread_mutex_lock(philo->forks[1]);
- thread_print(philo->settings, philo->id, g_fork_str);
- thread_print(philo->settings, philo->id, g_eat_str);
- philo->last_eaten = cur_time_sus();
- usleep(philo->settings->time_to_eat);
- ++philo->times_eaten;
- pthread_mutex_unlock(philo->forks[0]);
- pthread_mutex_unlock(philo->forks[1]);
- return ;
-}
-
-void *be_a_philosopher(void *inp)
-{
- t_philo *philo;
-
- philo = (t_philo *)inp;
- while (!philo->settings->end)
- {
- philo_think(philo->settings, philo->id);
- philo_eat(philo);
- philo_sleep(philo->settings, philo->id);
- }
- return (NULL);
-}
-
-pthread_mutex_t *init_forks(size_t count)
-{
- pthread_mutex_t *forks;
-
- forks = malloc(sizeof(pthread_mutex_t) * count);
- if (!forks)
- return (NULL);
- while (count > 0)
- {
- pthread_mutex_init(&forks[--count], NULL);
- }
- return (forks);
-}
-
-t_philo *build_philos(pthread_mutex_t *forks, t_settings *set)
-{
- t_philo *philos;
- size_t count;
-
- if (!forks)
- return (NULL);
- count = set->philo_count;
- philos = malloc(sizeof(t_philo) * count);
- if (!philos)
- return (NULL);
- philos[0].forks[1] = forks + count - 1;
- while (count > 0)
- {
- --count;
- philos[count].id = count + 1;
- philos[count].times_eaten = 0;
- philos[count].settings = set;
- philos[count].forks[0] = forks + count - count % 2;
- if (count > 0)
- philos[count].forks[1] = forks + count - (count + 1) % 2;
- }
- return (philos);
-}
-
-size_t ft_atos(const char *str)
-{
- size_t res;
-
- res = 0;
- while (*str == ' ')
- ++str;
- if (*str == '+')
- ++str;
- while ('0' <= *str && *str <= '9')
- {
- res *= 10;
- res += *str - '0';
- ++str;
- }
- return (res);
-}
-
-static size_t size_needed(int n)
-{
- size_t res;
-
- res = 1;
- if (n == 0)
- return (2);
- if (n < 0)
- ++res;
- while (n != 0)
- {
- ++res;
- n /= 10;
- }
- return (res);
-}
-
-char *ft_stoa(int n)
-{
- size_t size;
- char *res;
-
- size = size_needed(n);
- res = malloc(size * sizeof(char));
- if (res == NULL)
- return (res);
- res[--size] = '\0';
- if (n == 0 && res)
- res[0] = '0';
- else if (n < 0 && res)
- {
- res[0] = '-';
- res[--size] = '0' - (n % 10);
- n = -(n / 10);
- }
- while (n > 0 && res)
- {
- res[--size] = '0' + (n % 10);
- n /= 10;
- }
- return (res);
-}
-
-int ft_strcmp(const char *s1, const char *s2)
-{
- size_t i;
-
- i = 0;
- while (s1[i] == s2[i] && s1[i] && s2[i])
- ++i;
- return ((unsigned char)s1[i] - (unsigned char)s2[i]);
-}
-
-int parse_args(const char *arg, size_t *val)
-{
- int res;
- char *check_str;
-
- *val = ft_atos(arg);
- check_str = ft_stoa(*val);
- while (*arg == ' ' || *arg == '+')
- ++arg;
- res = ft_strcmp(check_str, arg);
- free(check_str);
- return (res);
-}
-
-int parse_arg(const char *arg, suseconds_t *val)
-{
- size_t tmp;
-
- if (parse_args(arg, &tmp))
- return (1);
- *val = tmp;
- if (*val != ((*val * 1000) / 1000))
- return (1);
- *val *= 1000;
- return (0);
-}
-
-int parse_input(int argc, char **argv, t_settings *set)
-{
- int res;
-
- if (argc != 5 && argc != 6)
- return (1);
- res = 0;
- res = res || parse_args(argv[1], &set->philo_count);
- res = res || parse_arg(argv[2], &set->time_to_die);
- res = res || parse_arg(argv[3], &set->time_to_eat);
- res = res || parse_arg(argv[4], &set->time_to_sleep);
- if (argc == 6)
- {
- res = res || parse_args(argv[5], &set->min_eats_num);
- if (set->min_eats_num == 0)
- set->end = 1;
- }
- else
- set->min_eats_num = 0;
- return (res);
-}
-
-int init_settings(int argc, char **argv, t_settings *set)
-{
- pthread_mutex_init(&set->terminal, NULL);
- set->end = 0;
- return (parse_input(argc, argv, set));
-}
-
// "pthread_detach(threads[count]);" should be sufficient
// instead of pthread_join(thread[count], NULL) but valgrind
// then shows leaks
-void cleanup(pthread_mutex_t *forks, t_philo *philos, pthread_t *threads,
+static void cleanup(pthread_mutex_t *forks, t_philo *philos, pthread_t *threads,
t_settings *set)
{
size_t count;
return ;
}
-void create_philos(t_philo *philos, pthread_t *threads, t_settings *set)
-{
- size_t count;
-
- count = set->philo_count;
- while (count > 0)
- {
- --count;
- philos[count].last_eaten = set->program_start;
- pthread_create(threads + count, NULL, be_a_philosopher, philos + count);
- }
- return ;
-}
-
-int philo_died(t_philo *philo, t_settings *set)
-{
- size_t i;
- suseconds_t now;
-
- i = 0;
- now = cur_time_sus();
- while (i < set->philo_count)
- {
- if ((now - philos[i].last_eaten) > set->time_to_die)
- {
- pthread_mutex_lock(&set->terminal);
- printf("%li %lu %s\n", (cur_time_sus() - set->program_start)
- / 1000, i + 1, g_die_str);
- set->end = 1;
- pthread_mutex_unlock(&set->terminal);
- return (1);
- }
- ++i;
- }
- return (0);
-}
-
-int all_full(t_philo *philos, t_settings *set)
-{
- size_t i;
-
- i = 0;
- while (i < set->philo_count)
- {
- if (philos[i].times_eaten < set->min_eats_num)
- return (0);
- ++i;
- }
- return (1);
-}
-
-suseconds_t time_to_starve(t_philo *philos, t_settings *set)
-{
- suseconds_t furthest_eaten;
- size_t i;
-
- i = 0;
- while (i < set->philo_count)
- {
- if (furthest_eaten > philos[i].last_eaten)
- furthest_eaten = philos[i].last_eaten;
- ++i;
- }
- return (set->time_to_die - (cur_time_sus() - furthest_eaten));
-}
-
-void check_death(t_philo *philos, t_settings *set)
-{
- while (!philo_died(philos, set))
- {
- if (all_full(philos, set))
- {
- pthread_mutex_lock(&set->terminal);
- printf("%li %s\n", (cur_time_sus() - set->program_start) / 1000,
- g_fed_str);
- set->end = 1;
- pthread_mutex_unlock(&set->terminal);
- return ;
- }
- usleep(time_to_starve(philos, set));
- }
-}
-
-void handle_single_philo(t_settings *set)
-{
- set->program_start = cur_time_sus();
- thread_print(set, 1, g_think_str);
- thread_print(set, 1, g_fork_str);
- usleep(set->time_to_die);
- thread_print(set, 1, g_die_str);
- return ;
-}
-
-int special_cases(t_settings *set)
+static int special_cases(t_settings *set)
{
if (set->end)
{
- printf("0 %s\n", g_fed_str);
+ printf("0 %s\n", G_FED_STR);
return (1);
}
if (set->philo_count == 1)
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* parsing.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/03/21 09:19:16 by ljiriste #+# #+# */
+/* Updated: 2024/03/21 10:30:32 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+static int parse_args(const char *arg, size_t *val)
+{
+ int res;
+ char *check_str;
+
+ *val = ft_atos(arg);
+ check_str = ft_stoa(*val);
+ while (*arg == ' ' || *arg == '+')
+ ++arg;
+ res = ft_strcmp(check_str, arg);
+ free(check_str);
+ return (res);
+}
+
+static int parse_arg(const char *arg, suseconds_t *val)
+{
+ size_t tmp;
+
+ if (parse_args(arg, &tmp))
+ return (1);
+ *val = tmp;
+ if (*val != ((*val * 1000) / 1000))
+ return (1);
+ *val *= 1000;
+ return (0);
+}
+
+int parse_input(int argc, char **argv, t_settings *set)
+{
+ int res;
+
+ if (argc != 5 && argc != 6)
+ return (1);
+ res = 0;
+ res = res || parse_args(argv[1], &set->philo_count);
+ res = res || parse_arg(argv[2], &set->time_to_die);
+ res = res || parse_arg(argv[3], &set->time_to_eat);
+ res = res || parse_arg(argv[4], &set->time_to_sleep);
+ if (argc == 6)
+ {
+ res = res || parse_args(argv[5], &set->min_eats_num);
+ if (set->min_eats_num == 0)
+ set->end = 1;
+ }
+ else
+ set->min_eats_num = 0;
+ return (res);
+}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/03/19 14:25:18 by ljiriste #+# #+# */
-/* Updated: 2024/03/19 14:33:17 by ljiriste ### ########.fr */
+/* Updated: 2024/03/21 10:16:40 by ljiriste ### ########.fr */
/* */
/* ************************************************************************** */
# include <pthread.h>
# include <sys/time.h>
+/*
+// Const globals must be static also which means
+// the following would be against the norm.
+// Instead I'll use macros...
+
+const char *g_fed_str = "All philosophers are well fed";
+const char *g_think_str = "is thinking";
+const char *g_fork_str = "has taken a fork";
+const char *g_eat_str = "is eating";
+const char *g_sleep_str = "is sleeping";
+const char *g_die_str = "died";
+*/
+
+# define G_FED_STR "All philosophers are well fed"
+# define G_THINK_STR "is thinking"
+# define G_FORK_STR "has taken a fork"
+# define G_EAT_STR "is eating"
+# define G_SLEEP_STR "is sleeping"
+# define G_DIE_STR "died"
+
+// unsigned long would be more apropriate for min_eats_num
+// but for the ease of parsing I'm using size_t (they are the same)
typedef struct s_settings
{
int end;
t_settings *settings;
} t_philo;
+// libft_extract.c
+int ft_strcmp(const char *s1, const char *s2);
+char *ft_stoa(int n);
+size_t ft_atos(const char *str);
+
+// init.c
+int init_settings(int argc, char **argv, t_settings *set);
+pthread_mutex_t *init_forks(size_t count);
+t_philo *build_philos(pthread_mutex_t *forks, t_settings *set);
+void create_philos(t_philo *philos, pthread_t *threads,
+ t_settings *set);
+
+// philos.c
+void *be_a_philosopher(void *inp);
+void handle_single_philo(t_settings *set);
+
+// check_death.c
+void check_death(t_philo *philos, t_settings *set);
+
+// parsing.c
+int parse_input(int argc, char **argv, t_settings *set);
+
+// time.c
+suseconds_t cur_time_sus(void);
+
+// print.c
+void thread_print(t_settings *set, size_t id, const char *message);
#endif //PHILO_H
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* philos.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/03/21 09:16:23 by ljiriste #+# #+# */
+/* Updated: 2024/03/21 10:26:14 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <stddef.h>
+#include <unistd.h>
+
+void philo_sleep(t_settings *set, size_t id)
+{
+ thread_print(set, id, G_SLEEP_STR);
+ usleep(set->time_to_sleep);
+ return ;
+}
+
+void philo_think(t_settings *set, size_t id)
+{
+ thread_print(set, id, G_THINK_STR);
+ return ;
+}
+
+void philo_eat(t_philo *philo)
+{
+ pthread_mutex_lock(philo->forks[0]);
+ thread_print(philo->settings, philo->id, G_FORK_STR);
+ pthread_mutex_lock(philo->forks[1]);
+ thread_print(philo->settings, philo->id, G_FORK_STR);
+ thread_print(philo->settings, philo->id, G_EAT_STR);
+ philo->last_eaten = cur_time_sus();
+ usleep(philo->settings->time_to_eat);
+ ++philo->times_eaten;
+ pthread_mutex_unlock(philo->forks[0]);
+ pthread_mutex_unlock(philo->forks[1]);
+ return ;
+}
+
+void *be_a_philosopher(void *inp)
+{
+ t_philo *philo;
+
+ philo = (t_philo *)inp;
+ while (!philo->settings->end)
+ {
+ philo_think(philo->settings, philo->id);
+ philo_eat(philo);
+ philo_sleep(philo->settings, philo->id);
+ }
+ return (NULL);
+}
+
+void handle_single_philo(t_settings *set)
+{
+ set->program_start = cur_time_sus();
+ thread_print(set, 1, G_THINK_STR);
+ thread_print(set, 1, G_FORK_STR);
+ usleep(set->time_to_die);
+ thread_print(set, 1, G_DIE_STR);
+ return ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* print.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/03/21 09:57:21 by ljiriste #+# #+# */
+/* Updated: 2024/03/21 09:58:12 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <stddef.h>
+#include <pthread.h>
+#include <stdio.h>
+
+void thread_print(t_settings *set, size_t id, const char *message)
+{
+ pthread_mutex_lock(&set->terminal);
+ if (set->end)
+ {
+ pthread_mutex_unlock(&set->terminal);
+ return ;
+ }
+ printf("%li %li %s\n", (cur_time_sus() - set->program_start) / 1000,
+ id, message);
+ pthread_mutex_unlock(&set->terminal);
+ return ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* time.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/03/21 09:55:45 by ljiriste #+# #+# */
+/* Updated: 2024/03/21 09:56:31 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "philo.h"
+#include <stddef.h>
+#include <sys/time.h>
+
+suseconds_t cur_time_sus(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return (tv.tv_sec * 1000000 + tv.tv_usec);
+}