Changeset a165a96 in rtems
- Timestamp:
- 02/23/17 14:43:41 (7 years ago)
- Branches:
- 5, master
- Children:
- 36635433
- Parents:
- c41b47e3
- git-author:
- Sebastian Huber <sebastian.huber@…> (02/23/17 14:43:41)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (02/28/17 08:09:19)
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
cpukit/libcsupport/src/termios.c
rc41b47e3 ra165a96 1021 1021 * Send characters to device-specific code 1022 1022 */ 1023 static void 1024 doTransmit (const char *buf, size_t len, rtems_termios_tty *tty) 1023 static size_t 1024 doTransmit (const char *buf, size_t len, rtems_termios_tty *tty, 1025 bool wait, bool nextWait) 1025 1026 { 1026 1027 unsigned int newHead; … … 1028 1029 rtems_interrupt_lock_context lock_context; 1029 1030 rtems_status_code sc; 1031 size_t todo; 1030 1032 1031 1033 if (tty->handler.mode == TERMIOS_POLLED) { 1032 1034 (*tty->handler.write)(ctx, buf, len); 1033 return; 1034 } 1035 1036 while (len) { 1035 return len; 1036 } 1037 1038 todo = len; 1039 1040 while (todo > 0) { 1037 1041 size_t nToCopy; 1038 1042 size_t nAvail; … … 1044 1048 1045 1049 rtems_termios_device_lock_acquire (ctx, &lock_context); 1046 while (newHead == tty->rawOutBuf.Tail) { 1047 tty->rawOutBufState = rob_wait; 1048 rtems_termios_device_lock_release (ctx, &lock_context); 1049 sc = rtems_semaphore_obtain( 1050 tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 1051 if (sc != RTEMS_SUCCESSFUL) 1052 rtems_fatal_error_occurred (sc); 1053 rtems_termios_device_lock_acquire (ctx, &lock_context); 1050 if (newHead == tty->rawOutBuf.Tail) { 1051 if (wait) { 1052 do { 1053 tty->rawOutBufState = rob_wait; 1054 rtems_termios_device_lock_release (ctx, &lock_context); 1055 sc = rtems_semaphore_obtain( 1056 tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); 1057 if (sc != RTEMS_SUCCESSFUL) 1058 rtems_fatal_error_occurred (sc); 1059 rtems_termios_device_lock_acquire (ctx, &lock_context); 1060 } while (newHead == tty->rawOutBuf.Tail); 1061 } else { 1062 rtems_termios_device_lock_release (ctx, &lock_context); 1063 return len - todo; 1064 } 1054 1065 } 1055 1066 1056 1067 /* Determine free space up to current tail or end of ring buffer */ 1057 nToCopy = len;1068 nToCopy = todo; 1058 1069 if (tty->rawOutBuf.Tail > tty->rawOutBuf.Head) { 1059 1070 /* Available space is contiguous from Head to Tail */ … … 1087 1098 1088 1099 buf += nToCopy; 1089 len -= nToCopy; 1090 } 1100 todo -= nToCopy; 1101 wait = nextWait; 1102 } 1103 1104 return len; 1091 1105 } 1092 1106 … … 1095 1109 const void *_buf, size_t len, struct rtems_termios_tty *tty) 1096 1110 { 1097 doTransmit (_buf, len, tty); 1111 doTransmit (_buf, len, tty, true, true); 1112 } 1113 1114 static bool 1115 canTransmit (rtems_termios_tty *tty, bool wait, size_t len) 1116 { 1117 rtems_termios_device_context *ctx; 1118 rtems_interrupt_lock_context lock_context; 1119 unsigned int capacity; 1120 1121 if (wait || tty->handler.mode == TERMIOS_POLLED) { 1122 return true; 1123 } 1124 1125 ctx = tty->device_context; 1126 rtems_termios_device_lock_acquire (ctx, &lock_context); 1127 capacity = (tty->rawOutBuf.Tail - tty->rawOutBuf.Head - 1) % 1128 tty->rawOutBuf.Size; 1129 rtems_termios_device_lock_release (ctx, &lock_context); 1130 return capacity >= len; 1098 1131 } 1099 1132 … … 1101 1134 * Handle output processing 1102 1135 */ 1103 static void1104 oproc (unsigned char c, struct rtems_termios_tty *tty)1136 static bool 1137 oproc (unsigned char c, rtems_termios_tty *tty, bool wait) 1105 1138 { 1106 1139 char buf[8]; … … 1119 1152 columnAdj = -oldColumn; 1120 1153 if (tty->termios.c_oflag & ONLCR) { 1154 len = 2; 1155 1156 if (!canTransmit (tty, wait, len)) { 1157 return false; 1158 } 1159 1121 1160 columnAdj = -oldColumn; 1122 1161 buf[0] = '\r'; 1123 1162 buf[1] = c; 1124 len = 2;1125 1163 } 1126 1164 break; … … 1128 1166 case '\r': 1129 1167 if ((tty->termios.c_oflag & ONOCR) && (oldColumn == 0)) 1130 return ;1168 return true; 1131 1169 if (tty->termios.c_oflag & OCRNL) { 1132 1170 buf[0] = '\n'; … … 1145 1183 len = (size_t) columnAdj; 1146 1184 1185 if (!canTransmit (tty, wait, len)) { 1186 return false; 1187 } 1188 1147 1189 for (i = 0; i < columnAdj; ++i) { 1148 1190 buf[i] = ' '; … … 1169 1211 } 1170 1212 1171 doTransmit (buf, len, tty);1213 return doTransmit (buf, len, tty, wait, true) > 0; 1172 1214 } 1173 1215 1174 1216 static uint32_t 1175 rtems_termios_write_tty ( struct rtems_termios_tty *tty, const char *buffer,1176 uint32_t initial_count) 1177 { 1217 rtems_termios_write_tty (rtems_termios_tty *tty, const char *buf, uint32_t len) 1218 { 1219 bool wait = true; 1178 1220 1179 1221 if (tty->termios.c_oflag & OPOST) { 1180 uint32_t count; 1181 1182 count = initial_count; 1183 1184 while (count--) 1185 oproc (*buffer++, tty); 1222 uint32_t todo = len; 1223 1224 while (todo > 0) { 1225 if (!oproc (*buf, tty, wait)) { 1226 break; 1227 } 1228 1229 ++buf; 1230 --todo; 1231 wait = false; 1232 } 1233 1234 return len - todo; 1186 1235 } else { 1187 doTransmit (buffer, initial_count, tty); 1188 } 1189 1190 return initial_count; 1236 return doTransmit (buf, len, tty, wait, false); 1237 } 1191 1238 } 1192 1239 … … 1223 1270 echobuf[0] = '^'; 1224 1271 echobuf[1] = c ^ 0x40; 1225 doTransmit (echobuf, 2, tty );1272 doTransmit (echobuf, 2, tty, true, true); 1226 1273 tty->column += 2; 1227 1274 } else { 1228 oproc (c, tty );1275 oproc (c, tty, true); 1229 1276 } 1230 1277 } … … 1283 1330 */ 1284 1331 while (tty->column > col) { 1285 doTransmit ("\b", 1, tty );1332 doTransmit ("\b", 1, tty, true, true); 1286 1333 tty->column--; 1287 1334 } … … 1289 1336 else { 1290 1337 if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) { 1291 doTransmit ("\b \b", 3, tty );1338 doTransmit ("\b \b", 3, tty, true, true); 1292 1339 if (tty->column) 1293 1340 tty->column--; 1294 1341 } 1295 1342 if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) { 1296 doTransmit ("\b \b", 3, tty );1343 doTransmit ("\b \b", 3, tty, true, true); 1297 1344 if (tty->column) 1298 1345 tty->column--; -
testsuites/libtests/termios09/init.c
rc41b47e3 ra165a96 56 56 int fds[DEVICE_COUNT]; 57 57 struct termios term[DEVICE_COUNT]; 58 int context_switch_counter; 59 rtems_id flush_task_id; 58 60 } test_context; 59 61 … … 909 911 clear_set_oflag(ctx, i, oflags, 0); 910 912 } 913 } 914 915 static void 916 set_self_prio(rtems_task_priority prio) 917 { 918 rtems_status_code sc; 919 920 sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio); 921 rtems_test_assert(sc == RTEMS_SUCCESSFUL); 922 } 923 924 static void flush_task(rtems_task_argument arg) 925 { 926 test_context *ctx = (test_context *) arg; 927 928 while (true) { 929 set_self_prio(1); 930 flush_output(ctx, INTERRUPT); 931 set_self_prio(2); 932 } 933 } 934 935 static void test_write(test_context *ctx) 936 { 937 tcflag_t oflags = OPOST | ONLCR | XTABS; 938 rtems_status_code sc; 939 size_t i = INTERRUPT; 940 device_context *dev = &ctx->devices[i]; 941 char buf[OUTPUT_BUFFER_SIZE]; 942 ssize_t n; 943 944 ctx->context_switch_counter = 0; 945 946 sc = rtems_task_create( 947 rtems_build_name('F', 'L', 'S', 'H'), 948 2, 949 RTEMS_MINIMUM_STACK_SIZE, 950 RTEMS_DEFAULT_MODES, 951 RTEMS_DEFAULT_ATTRIBUTES, 952 &ctx->flush_task_id 953 ); 954 rtems_test_assert(sc == RTEMS_SUCCESSFUL); 955 956 sc = rtems_task_start( 957 ctx->flush_task_id, 958 flush_task, 959 (rtems_task_argument) ctx 960 ); 961 rtems_test_assert(sc == RTEMS_SUCCESSFUL); 962 963 clear_output(ctx, i); 964 memset(buf, 'a', OUTPUT_BUFFER_SIZE); 965 966 n = write(ctx->fds[i], &buf[0], OUTPUT_BUFFER_SIZE); 967 rtems_test_assert(n == OUTPUT_BUFFER_SIZE - 1); 968 969 rtems_test_assert(ctx->context_switch_counter == 0); 970 971 n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 1], 1); 972 rtems_test_assert(n == 1); 973 974 rtems_test_assert(ctx->context_switch_counter == 2); 975 rtems_test_assert(dev->output_count == OUTPUT_BUFFER_SIZE); 976 rtems_test_assert(memcmp(dev->output_buf, buf, OUTPUT_BUFFER_SIZE) == 0); 977 978 clear_set_oflag(ctx, i, 0, oflags); 979 980 /* Ensure that ONLCR output expansion is taken into account */ 981 982 dev->tty->column = 0; 983 clear_output(ctx, i); 984 memset(buf, 'b', OUTPUT_BUFFER_SIZE - 1); 985 buf[OUTPUT_BUFFER_SIZE - 2] = '\n'; 986 987 n = write(ctx->fds[i], &buf[0], OUTPUT_BUFFER_SIZE - 3); 988 rtems_test_assert(n == OUTPUT_BUFFER_SIZE - 3); 989 990 rtems_test_assert(ctx->context_switch_counter == 2); 991 992 n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 3], 2); 993 rtems_test_assert(n == 1); 994 995 rtems_test_assert(ctx->context_switch_counter == 2); 996 997 n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 2], 1); 998 rtems_test_assert(n == 1); 999 1000 rtems_test_assert(ctx->context_switch_counter == 4); 1001 rtems_test_assert(dev->output_count == OUTPUT_BUFFER_SIZE); 1002 buf[OUTPUT_BUFFER_SIZE - 2] = '\r'; 1003 buf[OUTPUT_BUFFER_SIZE - 1] = '\n'; 1004 rtems_test_assert(memcmp(dev->output_buf, buf, OUTPUT_BUFFER_SIZE) == 0); 1005 1006 /* Ensure that XTABS output expansion is taken into account */ 1007 1008 dev->tty->column = 0; 1009 clear_output(ctx, i); 1010 memset(buf, 'c', OUTPUT_BUFFER_SIZE - 8); 1011 buf[OUTPUT_BUFFER_SIZE - 8] = '\t'; 1012 1013 n = write(ctx->fds[i], &buf[0], OUTPUT_BUFFER_SIZE - 9); 1014 rtems_test_assert(n == OUTPUT_BUFFER_SIZE - 9); 1015 1016 rtems_test_assert(ctx->context_switch_counter == 4); 1017 1018 n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 9], 2); 1019 rtems_test_assert(n == 1); 1020 1021 rtems_test_assert(ctx->context_switch_counter == 4); 1022 1023 n = write(ctx->fds[i], &buf[OUTPUT_BUFFER_SIZE - 8], 1); 1024 rtems_test_assert(n == 1); 1025 1026 rtems_test_assert(ctx->context_switch_counter == 6); 1027 rtems_test_assert(dev->output_count == OUTPUT_BUFFER_SIZE); 1028 memset(&buf[OUTPUT_BUFFER_SIZE - 8], ' ', 8); 1029 rtems_test_assert(memcmp(dev->output_buf, buf, OUTPUT_BUFFER_SIZE) == 0); 1030 1031 clear_set_oflag(ctx, i, oflags, 0); 1032 1033 sc = rtems_task_delete(ctx->flush_task_id); 1034 rtems_test_assert(sc == RTEMS_SUCCESSFUL); 911 1035 } 912 1036 … … 933 1057 test_xtabs(ctx); 934 1058 test_olcuc(ctx); 1059 test_write(ctx); 935 1060 936 1061 TEST_END(); … … 938 1063 } 939 1064 1065 static void switch_extension(Thread_Control *executing, Thread_Control *heir) 1066 { 1067 test_context *ctx = &test_instance; 1068 1069 ++ctx->context_switch_counter; 1070 } 1071 940 1072 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER 941 1073 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER … … 943 1075 #define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 5 944 1076 945 #define CONFIGURE_MAXIMUM_TASKS 11077 #define CONFIGURE_MAXIMUM_TASKS 2 946 1078 947 1079 #define CONFIGURE_MAXIMUM_SEMAPHORES 7 948 1080 949 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION 1081 #define CONFIGURE_INITIAL_EXTENSIONS \ 1082 { .thread_switch = switch_extension }, \ 1083 RTEMS_TEST_INITIAL_EXTENSION 950 1084 951 1085 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
Note: See TracChangeset
for help on using the changeset viewer.