ADHD: Daemon for watching A/V device events
Details
o Adds infrastructure to handle different threads w/ automatic startup.
Threads are declared with THREAD_DESCRIPTOR, and the system
infrastructure handles all the startup and management.
o Adds signal handling infrastructure; restarts threads on SIGHUP.
o Added command line argument processing.
Note that, at least, Goobuntu has a defect in getopt_long().
--option <optional-argument>
will yield a SEGV because 'optarg' is NULL.
--option=<optional-argument>
works, however.
Testing
Execute 'make' in the 'adhd' directory, and the project builds.
Execute 'gavd', and note the message output.
BUG=chromium-os:19558
TEST=See above
Change-Id: I1033af5690fac0052c1892a81e296b3d2538ae88
Signed-off-by: Taylor Hutt <thutt@chromium.org>
diff --git a/Makefile b/Makefile
index dca6bfb..82cbf70 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,9 @@
all: gavd
-gavd: # Google Audio Visual Daemon
+gavd:: lib
+
+lib gavd:: # Google Audio Visual Daemon
@$(call remake,$@)
clean:
diff --git a/defs/c.mk b/defs/c.mk
index 801298a..fe10cc2 100644
--- a/defs/c.mk
+++ b/defs/c.mk
@@ -6,7 +6,8 @@
COPTIONS = \
- -O3 \
+ -g \
+ -O2 \
-funit-at-a-time
# Compiler is too old to support
@@ -15,6 +16,18 @@
# -Wlarger-than=4096
# -Wsync-nand
+# Enable GC on unused functions and data
+CGC = \
+ -ffunction-sections \
+ -fdata-sections
+
+# Also need to link with '-Xlinker --library=pthread'.
+PTHREAD = \
+ -pthread
+
+LDGC = \
+ -Xlinker --gc-sections
+
CWARN = \
-Waddress \
-Waggregate-return \
@@ -57,7 +70,6 @@
-Woverlength-strings \
-Woverride-init \
-Wpacked \
- -Wpadded \
-Wparentheses \
-Wpointer-arith \
-Wpointer-sign \
@@ -82,7 +94,6 @@
-Wundef \
-Wuninitialized \
-Wunknown-pragmas \
- -Wunreachable-code \
-Wunsafe-loop-optimizations \
-Wunused-function \
-Wunused-label \
@@ -101,12 +112,15 @@
BOARD_INCLUDE = -DADHD_BOARD_INCLUDE='"board-generic.h"'
endif
-INCLUDES = -I$(ADHD_DIR)/include
+INCLUDES = \
+ -I$(ADHD_DIR)/include \
+ -I$(ADHD_SOURCE_DIR)
CFLAGS = \
- -ansi \
+ -std=gnu99 \
+ -MD \
$(INCLUDES) \
+ $(PTHREADS) \
$(BOARD_INCLUDE) \
- $(CWARN) $(COPTIONS)
-
-
+ -DBOARD='"$(BOARD)"' \
+ $(CWARN) $(COPTIONS) $(CGC) $(LDGC)
diff --git a/defs/make.mk b/defs/make.mk
index 5a10df9..615d10e 100644
--- a/defs/make.mk
+++ b/defs/make.mk
@@ -19,6 +19,8 @@
export ADHD_BUILD_DIR = $(ADHD_DIR)/build/development
endif
+GAVD_LIB = $(ADHD_BUILD_DIR)/lib/gavd.a
+
# mkdir: Creates a directory, and all its parents, if it does not exist.
#
mkdir = [ ! -d $(1) ] && \
@@ -40,4 +42,5 @@
-f $(ADHD_DIR)/$(1)/Makefile \
-C $(ADHD_BUILD_DIR)/$(1) \
VPATH=$(ADHD_DIR)/$(1) \
+ ADHD_SOURCE_DIR=$(ADHD_DIR)/$(1) \
$(1)
diff --git a/defs/utilities.mk b/defs/utilities.mk
index 954ce73..3a3c06d 100644
--- a/defs/utilities.mk
+++ b/defs/utilities.mk
@@ -10,4 +10,5 @@
# This makes it easy to ensure there are no host OS utility
# dependencies when cross compiling.
-MKDIR = mkdir
+MKDIR = /bin/mkdir
+AR = /usr/bin/ar
diff --git a/gavd/Makefile b/gavd/Makefile
index a5c8da2..d438b5e 100644
--- a/gavd/Makefile
+++ b/gavd/Makefile
@@ -3,10 +3,18 @@
# found in the LICENSE file.
include $(ADHD_DIR)/defs/definitions.mk
-CFILES = main.c
+CFILES = \
+ main.c \
+ signal_handling.c \
+ thread_management.c \
+ thread_gpio_headphone.c
+
OFILES = $(CFILES:.c=.o)
-LIBS =
+LIBS = $(GAVD_LIB)
gavd: $(OFILES) $(LIBS)
- $(CC) -o $@ $(OFILES) $(LIBS)
+ $(CC) -o $@ $(OFILES) $(LIBS) \
+ -Xlinker --library=pthread \
+ -Xlinker --script=$(ADHD_SOURCE_DIR)/ld.script
+-include *.d
diff --git a/include/board-x86-mario.h b/gavd/board-amd64-generic.h
similarity index 78%
rename from include/board-x86-mario.h
rename to gavd/board-amd64-generic.h
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-amd64-generic.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-tegra2_seaboard.h b/gavd/board-arm-generic.h
similarity index 89%
rename from include/board-tegra2_seaboard.h
rename to gavd/board-arm-generic.h
index afe7983..e0f3478 100644
--- a/include/board-tegra2_seaboard.h
+++ b/gavd/board-arm-generic.h
@@ -4,4 +4,7 @@
*/
#if !defined(_BOARD_TEGRA2_SEA_BOARD_H_)
#define _BOARD_TEGRA2_SEA_BOARD_H_
+
+#undef ADHD_GPIO_HEADPHONE
+
#endif
diff --git a/include/board-lumpy.h b/gavd/board-lumpy.h
similarity index 78%
rename from include/board-lumpy.h
rename to gavd/board-lumpy.h
index 98c0eeb..388f6d1 100644
--- a/include/board-lumpy.h
+++ b/gavd/board-lumpy.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_LUMPY_H_)
#define _BOARD_LUMPY_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-stumpy.h b/gavd/board-stumpy.h
similarity index 78%
rename from include/board-stumpy.h
rename to gavd/board-stumpy.h
index 109754b..fb627d3 100644
--- a/include/board-stumpy.h
+++ b/gavd/board-stumpy.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_STUMPY_H_)
#define _BOARD_STUMPY_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-tegra2_aebl.h b/gavd/board-tegra2_aebl.h
similarity index 76%
copy from include/board-tegra2_aebl.h
copy to gavd/board-tegra2_aebl.h
index fd505b2..16397ed 100644
--- a/include/board-tegra2_aebl.h
+++ b/gavd/board-tegra2_aebl.h
@@ -4,4 +4,8 @@
*/
#if !defined(_BOARD_TEGRA2_AEBL_H_)
#define _BOARD_TEGRA2_AEBL_H_
+
+#define ADHD_GPIO_HEADPHONE
+#define ADHD_GPIO_HEADPHONE_GPIO_NUMBER 185
+
#endif
diff --git a/include/board-tegra2_aebl.h b/gavd/board-tegra2_arthur.h
similarity index 76%
copy from include/board-tegra2_aebl.h
copy to gavd/board-tegra2_arthur.h
index fd505b2..16397ed 100644
--- a/include/board-tegra2_aebl.h
+++ b/gavd/board-tegra2_arthur.h
@@ -4,4 +4,8 @@
*/
#if !defined(_BOARD_TEGRA2_AEBL_H_)
#define _BOARD_TEGRA2_AEBL_H_
+
+#define ADHD_GPIO_HEADPHONE
+#define ADHD_GPIO_HEADPHONE_GPIO_NUMBER 185
+
#endif
diff --git a/include/board-tegra2_asymptote.h b/gavd/board-tegra2_asymptote.h
similarity index 77%
rename from include/board-tegra2_asymptote.h
rename to gavd/board-tegra2_asymptote.h
index 02eb6b2..adff541 100644
--- a/include/board-tegra2_asymptote.h
+++ b/gavd/board-tegra2_asymptote.h
@@ -4,4 +4,8 @@
*/
#if !defined(_BOARD_TEGRA2_ASYMPTOTE_H_)
#define _BOARD_TEGRA2_ASYMPTOTE_H_
+
+#define ADHD_GPIO_HEADPHONE
+#define ADHD_GPIO_HEADPHONE_GPIO_NUMBER 185
+
#endif
diff --git a/include/board-tegra2_aebl.h b/gavd/board-tegra2_dev-board-opengl.h
similarity index 88%
rename from include/board-tegra2_aebl.h
rename to gavd/board-tegra2_dev-board-opengl.h
index fd505b2..94a1b85 100644
--- a/include/board-tegra2_aebl.h
+++ b/gavd/board-tegra2_dev-board-opengl.h
@@ -4,4 +4,7 @@
*/
#if !defined(_BOARD_TEGRA2_AEBL_H_)
#define _BOARD_TEGRA2_AEBL_H_
+
+#undef ADHD_GPIO_HEADPHONE
+
#endif
diff --git a/include/board-tegra2_aebl.h b/gavd/board-tegra2_dev-board.h
similarity index 88%
copy from include/board-tegra2_aebl.h
copy to gavd/board-tegra2_dev-board.h
index fd505b2..94a1b85 100644
--- a/include/board-tegra2_aebl.h
+++ b/gavd/board-tegra2_dev-board.h
@@ -4,4 +4,7 @@
*/
#if !defined(_BOARD_TEGRA2_AEBL_H_)
#define _BOARD_TEGRA2_AEBL_H_
+
+#undef ADHD_GPIO_HEADPHONE
+
#endif
diff --git a/include/board-tegra2_aebl.h b/gavd/board-tegra2_generic.h
similarity index 88%
copy from include/board-tegra2_aebl.h
copy to gavd/board-tegra2_generic.h
index fd505b2..94a1b85 100644
--- a/include/board-tegra2_aebl.h
+++ b/gavd/board-tegra2_generic.h
@@ -4,4 +4,7 @@
*/
#if !defined(_BOARD_TEGRA2_AEBL_H_)
#define _BOARD_TEGRA2_AEBL_H_
+
+#undef ADHD_GPIO_HEADPHONE
+
#endif
diff --git a/include/board-tegra2_kaen.h b/gavd/board-tegra2_kaen.h
similarity index 76%
rename from include/board-tegra2_kaen.h
rename to gavd/board-tegra2_kaen.h
index 48e115b..49debb6 100644
--- a/include/board-tegra2_kaen.h
+++ b/gavd/board-tegra2_kaen.h
@@ -4,4 +4,8 @@
*/
#if !defined(_BOARD_TEGRA2_KAEN_H_)
#define _BOARD_TEGRA2_KAEN_H_
+
+#define ADHD_GPIO_HEADPHONE
+#define ADHD_GPIO_HEADPHONE_GPIO_NUMBER 185
+
#endif
diff --git a/include/board-tegra2_seaboard.h b/gavd/board-tegra2_seaboard.h
similarity index 77%
copy from include/board-tegra2_seaboard.h
copy to gavd/board-tegra2_seaboard.h
index afe7983..1aac002 100644
--- a/include/board-tegra2_seaboard.h
+++ b/gavd/board-tegra2_seaboard.h
@@ -4,4 +4,8 @@
*/
#if !defined(_BOARD_TEGRA2_SEA_BOARD_H_)
#define _BOARD_TEGRA2_SEA_BOARD_H_
+
+#define ADHD_GPIO_HEADPHONE
+#define ADHD_GPIO_HEADPHONE_GPIO_NUMBER 185
+
#endif
diff --git a/include/board-tegra2_seaboard.h b/gavd/board-tegra2_wario.h
similarity index 77%
copy from include/board-tegra2_seaboard.h
copy to gavd/board-tegra2_wario.h
index afe7983..1aac002 100644
--- a/include/board-tegra2_seaboard.h
+++ b/gavd/board-tegra2_wario.h
@@ -4,4 +4,8 @@
*/
#if !defined(_BOARD_TEGRA2_SEA_BOARD_H_)
#define _BOARD_TEGRA2_SEA_BOARD_H_
+
+#define ADHD_GPIO_HEADPHONE
+#define ADHD_GPIO_HEADPHONE_GPIO_NUMBER 185
+
#endif
diff --git a/include/board-x86-mario.h b/gavd/board-x86-agz
similarity index 78%
copy from include/board-x86-mario.h
copy to gavd/board-x86-agz
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-x86-agz
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-alex.h b/gavd/board-x86-alex.h
similarity index 78%
rename from include/board-x86-alex.h
rename to gavd/board-x86-alex.h
index aa504a1..fa48df3 100644
--- a/include/board-x86-alex.h
+++ b/gavd/board-x86-alex.h
@@ -4,4 +4,5 @@
*/
#if !defined(_BOARD_X86_ALEX_H_)
#define _BOARD_X86_ALEX_H_
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-mario.h b/gavd/board-x86-dogfood.h
similarity index 78%
copy from include/board-x86-mario.h
copy to gavd/board-x86-dogfood.h
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-x86-dogfood.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-mario.h b/gavd/board-x86-fruitloop.h
similarity index 78%
copy from include/board-x86-mario.h
copy to gavd/board-x86-fruitloop.h
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-x86-fruitloop.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-mario.h b/gavd/board-x86-generic
similarity index 78%
copy from include/board-x86-mario.h
copy to gavd/board-x86-generic
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-x86-generic
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-mario.h b/gavd/board-x86-mario.h
similarity index 78%
copy from include/board-x86-mario.h
copy to gavd/board-x86-mario.h
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-x86-mario.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-mario.h b/gavd/board-x86-mario64.h
similarity index 78%
copy from include/board-x86-mario.h
copy to gavd/board-x86-mario64.h
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-x86-mario64.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-mario.h b/gavd/board-x86-pineview.h
similarity index 78%
copy from include/board-x86-mario.h
copy to gavd/board-x86-pineview.h
index 9ed5049..8e66d6f 100644
--- a/include/board-x86-mario.h
+++ b/gavd/board-x86-pineview.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_MARIO_H_)
#define _BOARD_X86_MARIO_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/include/board-x86-zgb.h b/gavd/board-x86-zgb.h
similarity index 78%
rename from include/board-x86-zgb.h
rename to gavd/board-x86-zgb.h
index 123cd86..fcfd48b 100644
--- a/include/board-x86-zgb.h
+++ b/gavd/board-x86-zgb.h
@@ -4,4 +4,6 @@
*/
#if !defined(_BOARD_X86_ZGB_H_)
#define _BOARD_X86_ZGB_H_
+
+#undef ADHD_GPIO_HEADPHONE /* No GPIO headphone switch. */
#endif
diff --git a/gavd/board.h b/gavd/board.h
new file mode 100644
index 0000000..6b647c1
--- /dev/null
+++ b/gavd/board.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#if !defined(_BOARD_GENERIC_H_)
+#define _BOARD_GENERIC_H_
+
+#define ADHD_TARGET_MACHINE BOARD
+#include ADHD_BOARD_INCLUDE
+
+#if !defined(ADHD_GPIO_HEADPHONE)
+#define adhd_gpio_headphone 0
+#undef ADHD_GPIO_HEADPHONE_GPIO_NUMBER
+#else
+#define adhd_gpio_headphone 1
+#if !defined(ADHD_GPIO_HEADPHONE_GPIO_NUMBER)
+#error "ADHD_GPIO_HEADPHONE_GPIO_NUMBER must be defined."
+#endif
+#endif
+#endif
diff --git a/gavd/ld.script b/gavd/ld.script
new file mode 100644
index 0000000..63a97de
--- /dev/null
+++ b/gavd/ld.script
@@ -0,0 +1,214 @@
+/* This script was generated by using '-Xlinker --verbose' on a gcc command line.
+ * It was then hand-modified to add the '.thread_info' section.
+ */
+
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rela.dyn :
+ {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+ *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+ *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+ *(.rela.ifunc)
+ }
+ .rela.plt :
+ {
+ *(.rela.plt)
+ PROVIDE_HIDDEN (__rela_iplt_start = .);
+ *(.rela.iplt)
+ PROVIDE_HIDDEN (__rela_iplt_end = .);
+ }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0x90909090
+ .plt : { *(.plt) *(.iplt) }
+ .text :
+ {
+ *(.text.unlikely .text.*_unlikely)
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ } =0x90909090
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x90909090
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ /* Thread Local Storage sections */
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) *(.igot) }
+ . = DATA_SEGMENT_RELRO_END (24, .);
+ .got.plt : { *(.got.plt) *(.igot.plt) }
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .; PROVIDE (edata = .);
+ __bss_start = .;
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we don't
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ .lbss :
+ {
+ *(.dynlbss)
+ *(.lbss .lbss.* .gnu.linkonce.lb.*)
+ *(LARGE_COMMON)
+ }
+ . = ALIGN(64 / 8);
+ .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+ {
+ *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+ }
+ .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+ {
+ *(.ldata .ldata.* .gnu.linkonce.l.*)
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ .thread_descriptor : {
+ __thread_descriptor_beg = . ;
+ *(.thread_descriptor)
+ __thread_descriptor_end = . ;
+ }
+ . = ALIGN(64 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/gavd/main.c b/gavd/main.c
index b397141..4834ad2 100644
--- a/gavd/main.c
+++ b/gavd/main.c
@@ -3,11 +3,108 @@
* found in the LICENSE file.
*/
+#include <errno.h>
+#include <getopt.h>
#include <stdio.h>
-#include ADHD_BOARD_INCLUDE
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "verbose.h"
+#include "signal_handling.h"
+#include "thread_management.h"
+#include "board.h"
-int main(void)
+static const char * const program_name = "gavd";
+
+static void help(void)
{
- printf("Google A/V Daemon\n");
+ /* TODO(thutt): Add help */
+}
+
+static void process_arguments(int argc, char **argv)
+{
+ static struct option options[] = {
+ {
+ .name = "help",
+ .has_arg = no_argument,
+ .flag = NULL,
+ .val = 256
+ },
+ {
+ .name = "verbose",
+ .has_arg = optional_argument,
+ .flag = NULL,
+ .val = 257
+ },
+ };
+
+ while (1) {
+ int option_index = 0;
+ const int choice = getopt_long(argc, argv, "", options, &option_index);
+
+ if (choice == -1) {
+ break;
+ }
+
+ switch (choice) {
+ case 256:
+ help();
+ break;
+
+ case 257:
+ /* Goobuntu has a defect with 'optarg'. If '--verbose 1'
+ * is used, 'optarg' will be NULL. Use '--verbose=1'.
+ */
+ verbose_set((unsigned)atoi(optarg));
+ break;
+
+ default:
+ printf("?? getopt returned character code 0%o ??\n", choice);
+ }
+ }
+}
+
+static void daemonize(void)
+{
+ pid_t child_pid;
+
+ child_pid = fork();
+ if (child_pid != 0) {
+ verbose_log(0, LOG_INFO, "Child process: '%u'.", child_pid);
+ exit(0);
+ }
+
+ /* Now running as daemon.
+ *
+ * TODO(thutt): Detach from console.
+ * TODO(thutt): close stdin/stdout/stderr
+ */
+ verbose_log(0, LOG_INFO, "%s: started", __FUNCTION__);
+ if (chdir("/") != 0) {
+ verbose_log(0, LOG_ERR, "Failed to chdir('/')");
+ exit(-errno);
+ }
+
+ signal_start();
+ threads_start();
+
+ while(!threads_quit_daemon()) {
+ sleep(3);
+ }
+
+ verbose_log(0, LOG_INFO, "%s: stopped", program_name);
+}
+
+int main(int argc, char **argv)
+{
+ process_arguments(argc, argv);
+ verbose_initialize(program_name);
+
+ verbose_log(0, LOG_INFO, "compiled for target machine: '%s'",
+ ADHD_TARGET_MACHINE);
+
+ daemonize();
+
+ verbose_finalize();
return 0;
}
diff --git a/gavd/signal_handling.c b/gavd/signal_handling.c
new file mode 100644
index 0000000..13e9ade
--- /dev/null
+++ b/gavd/signal_handling.c
@@ -0,0 +1,66 @@
+
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <assert.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#include "verbose.h"
+#include "thread_management.h"
+#include "signal_handling.h"
+
+static void signal_handle_sighup(int signum,
+ siginfo_t *siginfo,
+ void *ucontext)
+{
+ verbose_log(8, LOG_INFO, "%s", __FUNCTION__);
+ signum = signum; /* Silence compiler warning. */
+ siginfo = siginfo; /* Silence compiler warning. */
+ ucontext = ucontext; /* Silence compiler warning. */
+ threads_kill_all();
+ threads_start();
+}
+
+static void signal_start_sighup(void)
+{
+ struct sigaction action;
+ sigset_t sa_mask;
+
+ sigemptyset(&sa_mask);
+ action.sa_mask = sa_mask;
+ action.sa_flags = SA_SIGINFO; /* Use sa.sigaction, not sa_handler. */
+ action.sa_sigaction = signal_handle_sighup;
+ sigaction(SIGHUP, &action, NULL);
+}
+
+static void signal_handle_sigterm(int signum,
+ siginfo_t *siginfo,
+ void *ucontext)
+{
+ verbose_log(8, LOG_INFO, "%s", __FUNCTION__);
+ signum = signum; /* Silence compiler warning. */
+ siginfo = siginfo; /* Silence compiler warning. */
+ ucontext = ucontext; /* Silence compiler warning. */
+ thread_management.quit = 1;
+}
+
+static void signal_start_sigterm(void)
+{
+ struct sigaction action;
+ sigset_t sa_mask;
+
+ sigemptyset(&sa_mask);
+ action.sa_mask = sa_mask;
+ action.sa_flags = SA_SIGINFO; /* Use sa.sigaction, not sa_handler. */
+ action.sa_sigaction = signal_handle_sigterm;
+ sigaction(SIGTERM, &action, NULL);
+}
+
+void signal_start(void)
+{
+ verbose_log(5, LOG_INFO, "%s", __FUNCTION__);
+ signal_start_sighup();
+ signal_start_sigterm();
+}
diff --git a/include/board-x86-zgb.h b/gavd/signal_handling.h
similarity index 66%
copy from include/board-x86-zgb.h
copy to gavd/signal_handling.h
index 123cd86..7b0dfab 100644
--- a/include/board-x86-zgb.h
+++ b/gavd/signal_handling.h
@@ -2,6 +2,8 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
-#if !defined(_BOARD_X86_ZGB_H_)
-#define _BOARD_X86_ZGB_H_
+#if !defined(_SIGNAL_HANDLING_H_)
+#define _SIGNAL_HANDLING_H_
+
+void signal_start(void);
#endif
diff --git a/gavd/thread_gpio_headphone.c b/gavd/thread_gpio_headphone.c
new file mode 100644
index 0000000..ff2b434
--- /dev/null
+++ b/gavd/thread_gpio_headphone.c
@@ -0,0 +1,29 @@
+
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <assert.h>
+#include <unistd.h>
+
+#include "board.h"
+
+#if defined(ADHD_GPIO_HEADPHONE)
+#include "verbose.h"
+#include "thread_management.h"
+
+
+static void *gpio_headphone(void *arg)
+{
+ verbose_log(5, LOG_INFO, "%s: start", __FUNCTION__);
+ arg = arg; /* Silence compiler warning. */
+
+ while (!thread_management.exit) {
+ sleep(1);
+ }
+ verbose_log(5, LOG_INFO, "%s exited", __FUNCTION__);
+ return NULL;
+}
+
+THREAD_DESCRIPTOR("GPIO Headphone", gpio_headphone);
+#endif
diff --git a/gavd/thread_management.c b/gavd/thread_management.c
new file mode 100644
index 0000000..62e47d2
--- /dev/null
+++ b/gavd/thread_management.c
@@ -0,0 +1,73 @@
+
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <assert.h>
+#include <pthread.h>
+#include <limits.h>
+
+#include "board.h"
+#include "verbose.h"
+#include "thread_management.h"
+
+extern unsigned char __thread_descriptor_beg;
+extern unsigned char __thread_descriptor_end;
+
+thread_management_t thread_management;
+
+static unsigned threads_number_of_descriptors(void)
+{
+ unsigned long length = ((unsigned long)(&__thread_descriptor_end -
+ &__thread_descriptor_beg) /
+ sizeof(thread_descriptor_t));
+
+ assert(length <= UINT_MAX);
+ return (unsigned)length;
+}
+
+static thread_descriptor_t *threads_first_descriptor(void)
+{
+ return (thread_descriptor_t *)&__thread_descriptor_beg;
+}
+
+static thread_descriptor_t *threads_last_descriptor(void)
+{
+ unsigned n = threads_number_of_descriptors();
+ thread_descriptor_t *desc = threads_first_descriptor() + (n - 1);
+ return desc;
+}
+
+void threads_start(void)
+{
+ thread_descriptor_t *desc = threads_first_descriptor();
+ unsigned n = threads_number_of_descriptors();
+
+ thread_management.exit = 0;
+ thread_management.quit = 0;
+ while (n-- > 0) {
+ verbose_log(1, LOG_INFO, "%s: '%s'", __FUNCTION__, desc->name);
+ pthread_create(&desc->thread, NULL, desc->start_routine, desc);
+ ++desc;
+ }
+}
+
+void threads_kill_all(void)
+{
+ /* Threads are killed in the reverse order of creation. */
+ unsigned n = threads_number_of_descriptors();
+ thread_descriptor_t *desc = threads_last_descriptor();
+
+ thread_management.exit = 1;
+ while (n-- > 0) {
+ verbose_log(5, LOG_INFO, "%s: '%s'", __FUNCTION__, desc->name);
+ pthread_join(desc->thread, NULL);
+ --desc;
+ }
+ thread_management.exit = 0;
+}
+
+unsigned threads_quit_daemon(void)
+{
+ return thread_management.quit;
+}
diff --git a/gavd/thread_management.h b/gavd/thread_management.h
new file mode 100644
index 0000000..e51972d
--- /dev/null
+++ b/gavd/thread_management.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#if !defined(_THREAD_MANAGEMENT_H_)
+#define _THREAD_MANAGEMENT_H_
+#include <pthread.h>
+
+typedef struct thread_descriptor_t {
+ void *(*start_routine)(void*); /* pthread start routine */
+ const char *name;
+
+ pthread_t thread;
+ void *data;
+} thread_descriptor_t;
+
+#define THREAD_DESCRIPTOR(_name, _start_routine) \
+ thread_descriptor_t \
+ __attribute__((section(".thread_descriptor"))) \
+ __thread_descriptor_##_start_routine = { \
+ .name = _name, \
+ .start_routine = _start_routine, \
+ }
+
+typedef struct thread_management_t {
+ unsigned quit; /* quit == 0 => Daemon continues to run.
+ * quit != 1 => Daemon exits.
+ */
+ unsigned exit; /* exit == 0 => Continue running.
+ * exit != 0 => Thread should exit.
+ *
+ * There is no mutex controlling this
+ * data because it is written by one
+ * function. All readers will exit
+ * when a non-zero value is present.
+ */
+} thread_management_t;
+
+extern thread_management_t thread_management;
+
+void threads_start(void);
+void threads_kill_all(void);
+unsigned threads_quit_daemon(void);
+#endif
diff --git a/include/board-generic.h b/include/board-generic.h
deleted file mode 100644
index 9e11a19..0000000
--- a/include/board-generic.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#if !defined(_BOARD_GENERIC_H_)
-#define _BOARD_GENERIC_H_
-#endif
diff --git a/include/verbose.h b/include/verbose.h
new file mode 100644
index 0000000..9faab43
--- /dev/null
+++ b/include/verbose.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#if !defined(_VERBOSE_H_)
+#define _VERBOSE_H_
+#include <syslog.h>
+
+/* verbose_set: Set verbosity of the daemon.
+ *
+ * verbosity: The new level of verbosity.
+ * Higher levels mean more diagnostic output will be produced.
+ * If not called, the verbosity level is 0.
+ *
+ * A verbosity level of 0 means minimal output.
+ */
+void verbose_set(unsigned verbosity);
+
+/* verbose_log: Log information using syslog
+ *
+ * verbosity_level : Message is logged only if 'level <= current
+ * verbosity level'.
+ * log_level : LOG_EMERG system is unusable
+ * LOG_ALERT action must be taken immediately
+ * LOG_CRIT critical conditions
+ * LOG_ERR error conditions
+ * LOG_WARNING warning conditions
+ * LOG_NOTICE normal, but significant, condition
+ * LOG_INFO informational message
+ * LOG_DEBUG debug-level message
+ * format: printf()-style format specifier
+ * ... : arguments to use in expansion of 'format'.
+ */
+void verbose_log(unsigned verbosity_level,
+ int log_level,
+ const char *format,
+ ...)
+ __attribute__((format(printf, 3, 4)));
+
+void verbose_initialize(const char *program_name);
+void verbose_finalize(void);
+#endif
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..d2684f4
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,13 @@
+# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+include $(ADHD_DIR)/defs/definitions.mk
+
+CFILES = \
+ verbose.c
+
+OFILES = $(CFILES:.c=.o)
+
+lib: $(OFILES)
+ $(AR) -r $(GAVD_LIB) $(OFILES) 2>/dev/null
+
diff --git a/lib/verbose.c b/lib/verbose.c
new file mode 100644
index 0000000..2522a52
--- /dev/null
+++ b/lib/verbose.c
@@ -0,0 +1,51 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include <stdarg.h>
+#include <stdio.h>
+#include <syslog.h>
+#include "verbose.h"
+
+static unsigned verbose_level = 0;
+static const int log_options = LOG_NDELAY | LOG_PID;
+static const int log_facility = LOG_DAEMON; /* /var/log/daemon.log */
+static char log_buffer[1024];
+
+
+void verbose_set(unsigned verbosity)
+{
+ verbose_level = verbosity;
+}
+
+void verbose_initialize(const char *program_name)
+{
+ openlog(program_name, log_options, log_facility);
+}
+
+void verbose_finalize(void)
+{
+ closelog();
+}
+
+
+/*
+ * log_level values:
+*/
+void verbose_log(unsigned verbosity_level,
+ int log_level,
+ const char *format,
+ ...)
+{
+ if (verbosity_level <= verbose_level) {
+ const size_t log_buffer_len = (sizeof(log_buffer) /
+ sizeof(log_buffer[0]));
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(log_buffer, log_buffer_len, format, ap);
+ log_buffer[log_buffer_len - 1] = '\0';
+ va_end(ap);
+ syslog(log_facility | log_level, "%s", log_buffer);
+ }
+}