summaryrefslogtreecommitdiff
path: root/arch/arm/plat-omap/include/syslink/igateprovider.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap/include/syslink/igateprovider.h')
-rw-r--r--arch/arm/plat-omap/include/syslink/igateprovider.h123
1 files changed, 123 insertions, 0 deletions
diff --git a/arch/arm/plat-omap/include/syslink/igateprovider.h b/arch/arm/plat-omap/include/syslink/igateprovider.h
new file mode 100644
index 00000000000..c4ac4ab91c9
--- /dev/null
+++ b/arch/arm/plat-omap/include/syslink/igateprovider.h
@@ -0,0 +1,123 @@
+/*
+ * igateprovider.h
+ *
+ * Interface implemented by all gate providers.
+ *
+ * Copyright (C) 2008-2009 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ *
+ */
+/** ============================================================================
+ * Gates are used serialize access to data structures that are used by more
+ * than one thread.
+ *
+ * Gates are responsible for ensuring that only one out of multiple threads
+ * can access a data structure at a time. There
+ * are important scheduling latency and performance considerations that
+ * affect the "type" of gate used to protect each data structure. For
+ * example, the best way to protect a shared counter is to simply disable
+ * all interrupts before the update and restore the interrupt state after
+ * the update; disabling all interrupts prevents all thread switching, so
+ * the update is guaranteed to be "atomic". Although highly efficient, this
+ * method of creating atomic sections causes serious system latencies when
+ * the time required to update the data structure can't be bounded.
+ *
+ * For example, a memory manager's list of free blocks can grow indefinitely
+ * long during periods of high fragmentation. Searching such a list with
+ * interrupts disabled would cause system latencies to also become unbounded.
+ * In this case, the best solution is to provide a gate that suspends the
+ * execution of threads that try to enter a gate that has already been
+ * entered; i.e., the gate "blocks" the thread until the thread
+ * already in the gate leaves. The time required to enter and leave the
+ * gate is greater than simply enabling and restoring interrupts, but since
+ * the time spent within the gate is relatively large, the overhead caused by
+ * entering and leaving gates will not become a significant percentage of
+ * overall system time. More importantly, threads that do not need to
+ * access the shared data structure are completely unaffected by threads
+ * that do access it.
+ * ============================================================================
+ */
+
+
+#ifndef _IGATEPROVIDER_H_
+#define _IGATEPROVIDER_H_
+
+
+/* Invalid Igate */
+#define IGATEPROVIDER_NULL (struct igateprovider_object *)0xFFFFFFFF
+
+/* Gates with this "quality" may cause the calling thread to block;
+ * i.e., suspend execution until another thread leaves the gate. */
+#define IGateProvider_Q_BLOCKING 1
+
+/* Gates with this "quality" allow other threads to preempt the thread
+ * that has already entered the gate. */
+#define IGateProvider_Q_PREEMPTING 2
+
+/* Object embedded in other Gate modules. (Inheritance) */
+#define IGATEPROVIDER_SUPEROBJECT \
+ int *(*enter)(void *); \
+ void (*leave)(void *, int *)
+
+#define IGATEPROVIDER_OBJECTINITIALIZER(x, y) \
+ do { \
+ ((struct igateprovider_object *)(x))->enter = y##_enter; \
+ ((struct igateprovider_object *)(x))->leave = y##_leave; \
+ } while (0)
+
+
+/* Structure for generic gate instance */
+struct igateprovider_object {
+ IGATEPROVIDER_SUPEROBJECT;
+};
+
+
+/*
+ * Enter this gate
+ *
+ * Each gate provider can implement mutual exclusion using different
+ * algorithms; e.g., disabling all scheduling, disabling the scheduling
+ * of all threads below a specified "priority level", suspending the
+ * caller when the gate has been entered by another thread and
+ * re-enabling it when the the other thread leaves the gate. However,
+ * in all cases, after this method returns that caller has exclusive
+ * access to the data protected by this gate.
+ *
+ * A thread may reenter a gate without blocking or failing.
+ */
+static inline int *igateprovider_enter(struct igateprovider_object *handle)
+{
+ int *key = NULL;
+
+ if (handle != IGATEPROVIDER_NULL)
+ key = (handle->enter)((void *)handle);
+ return key;
+}
+
+
+/*
+ * Leave this gate
+ *
+ * This method is only called by threads that have previously entered
+ * this gate via `{@link #enter}`. After this method returns, the
+ * caller must not access the data structure protected by this gate
+ * (unless the caller has entered the gate more than once and other
+ * calls to `leave` remain to balance the number of previous
+ * calls to `enter`).
+ */
+static inline void igateprovider_leave(struct igateprovider_object *handle,
+ int *key)
+{
+ if (handle != IGATEPROVIDER_NULL)
+ (handle->leave)((void *)handle, key);
+}
+
+#endif /* ifndef _IGATEPROVIDER_H_ */