diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 5809c1ea95e08a3249df733a6c6753c8a4548fe3..b8eddd9eeb22aa85904e7f8eb888f63dd01b29af 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -39,6 +39,14 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#if defined(__FreeBSD__)
+#include <kvm.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <libprocstat.h>
+#endif
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
@@ -100,16 +108,11 @@ static int check_sctp_sndrcvinfo(struct sctp_sndrcvinfo_expr *expr,
 				 char** error);
 #endif
 
+#if defined(linux)
 /* Provide a wrapper for the Linux gettid() system call (glibc does not). */
 static pid_t gettid(void)
 {
-#ifdef linux
 	return syscall(__NR_gettid);
-#endif
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
-	/* TODO(ncardwell): Implement me. XXX */
-	return 0;
-#endif /* defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)*/
 }
 
 /* Read a whole file into the given buffer of the given length. */
@@ -157,6 +160,50 @@ static bool is_thread_sleeping(pid_t process_id, pid_t thread_id)
 
 	return is_sleeping;
 }
+#elif defined(__FreeBSD__)
+static bool is_thread_sleeping(pid_t process_id, int thread_id)
+{
+	struct procstat *procstat;
+	struct kinfo_proc *kinfo_proc;
+	unsigned int i, count;
+	bool is_sleeping;
+
+	procstat = procstat_open_sysctl();
+	if (procstat == NULL) {
+		die("procstat_open_sysctl() failed\n");
+	}
+	/* Get the information for all threads belonging to the given process.
+	 * The number of entries (one for each thread) is returned in count.
+	 */
+	kinfo_proc = procstat_getprocs(procstat,
+	                               KERN_PROC_PID | KERN_PROC_INC_THREAD,
+	                               process_id, &count);
+	if (kinfo_proc == NULL) {
+		die("procstat_getprocs() failed\n");
+	}
+	/* Do a linear search to the entry for the requested thread.
+	 * Since we have only two threads, that's OK performance-wise.
+	 */
+	for (i = 0; i < count; i++) {
+		if (kinfo_proc[i].ki_tid == thread_id)
+			break;
+	}
+	/* Die, if we can't find the entry for the requested thread. */
+	if (i == count)
+		die("unable to get state of thread %d\n", thread_id);
+	is_sleeping = (kinfo_proc[i].ki_stat == SSLEEP);
+	/* Cleanup the allocated data structures. */
+	procstat_freeprocs(procstat, kinfo_proc);
+	procstat_close(procstat);
+	return is_sleeping;
+}
+#else
+static bool is_thread_sleeping(pid_t process_id, int thread_id)
+{
+	die("is_thread_sleeping not implemented on this platform\n");
+	return true;
+}
+#endif
 
 /* Returns number of expressions in the list. */
 static int expression_list_length(struct expression_list *list)
@@ -6123,11 +6170,19 @@ static void enqueue_system_call(
 
 	/* Wait for the syscall thread to block or finish the call. */
 	while (!done) {
+#if defined(linux)
+		pid_t thread_id;
+#elif defined(__FreeBSD__)
+		int thread_id;
+#else
+		int thread_id; /* FIXME */
+#endif
+
 		/* Unlock and yield so the system call thread can make
 		 * the system call in a timely fashion.
 		 */
 		DEBUGP("main thread: unlocking and yielding\n");
-		pid_t thread_id = state->syscalls->thread_id;
+		thread_id = state->syscalls->thread_id;
 		run_unlock(state);
 		if (yield() != 0)
 			die_perror("yield");
@@ -6187,9 +6242,15 @@ static void *system_call_thread(void *arg)
 	DEBUGP("syscall thread: starting and locking\n");
 	run_lock(state);
 
+#if defined(linux)
 	state->syscalls->thread_id = gettid();
 	if (state->syscalls->thread_id < 0)
 		die_perror("gettid");
+#elif defined(__FreeBSD__)
+	state->syscalls->thread_id = pthread_getthreadid_np();
+#else
+	state->syscalls->thread_id = 0		/* FIXME */
+#endif
 
 	while (!done) {
 		DEBUGP("syscall thread: in state %d\n",
diff --git a/gtests/net/packetdrill/run_system_call.h b/gtests/net/packetdrill/run_system_call.h
index 570b7fa7e496bd728015b5b56672411250156234..7dbd0887748c3f0dec0114cc8ddfc8f0333a620d 100644
--- a/gtests/net/packetdrill/run_system_call.h
+++ b/gtests/net/packetdrill/run_system_call.h
@@ -51,7 +51,13 @@ struct syscalls {
 
 	/* Handles for the syscall thread, for blocking system calls. */
 	pthread_t thread;		/* pthread thread handle */
+#if defined(linux)
 	pid_t thread_id;		/* kernel thread ID  */
+#elif defined(__FreeBSD__)
+	int thread_id;
+#else
+	int thread_id;			/* FIXME */
+#endif
 
 	/* The main thread waits on this condition variable. The
 	 * system call thread signals this when it has finished